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

jackietien pushed a commit to branch ty/TableIT
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/ty/TableIT by this push:
     new a22fe7c72b1 Add IT for IoTDBDatetimeFormatIT and IoTDBNestedQueryIT
a22fe7c72b1 is described below

commit a22fe7c72b103fbea8b87d64a9579fe63b87818b
Author: JackieTien97 <[email protected]>
AuthorDate: Wed Jul 24 12:20:33 2024 +0800

    Add IT for IoTDBDatetimeFormatIT and IoTDBNestedQueryIT
---
 .../scalar/IoTDBDiffFunctionIT.java                | 367 ++++++++++------
 .../it/query/old/IoTDBDatetimeFormatIT.java        | 157 +++++++
 .../it/query/old/IoTDBNestedQueryIT.java           | 460 +++++++++++++++++++++
 .../scalar/IoTDBDiffFunctionIT.java                | 348 +++++-----------
 .../plan/relational/analyzer/Analyzer.java         |   4 +
 .../predicate/ConvertPredicateToFilterVisitor.java |   9 +-
 .../planner/ir/NormalizeOrExpressionRewriter.java  |  15 +-
 .../plan/relational/sql/parser/AstBuilder.java     |  17 +
 .../db/relational/grammar/sql/RelationalSql.g4     |   6 +-
 9 files changed, 1008 insertions(+), 375 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBDiffFunctionIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBDiffFunctionIT.java
index 77f90aa993a..970bbc2a745 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBDiffFunctionIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBDiffFunctionIT.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.ClusterIT;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
-import org.apache.iotdb.itbase.env.BaseEnv;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -31,35 +30,33 @@ import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
-import java.sql.Connection;
-import java.sql.Statement;
-
+import static org.apache.iotdb.db.it.utils.TestUtils.prepareData;
 import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest;
+import static org.apache.iotdb.itbase.constant.TestConstant.DEVICE;
+import static org.apache.iotdb.itbase.constant.TestConstant.TIMESTAMP_STR;
 
 @RunWith(IoTDBTestRunner.class)
 @Category({LocalStandaloneIT.class, ClusterIT.class})
 public class IoTDBDiffFunctionIT {
-
-  private static final String DATABASE_NAME = "db";
-
-  // 2 devices 4 regions
   protected static final String[] SQLs =
       new String[] {
-        "CREATE DATABASE " + DATABASE_NAME,
-        "use " + DATABASE_NAME,
-        "create table table1(device_id STRING ID, s1 INT32 MEASUREMENT, FLOAT 
INT32 MEASUREMENT);",
-        "INSERT INTO table1(time,device_id,s1,s2) values(1, 'd1', 1, 1)",
-        "INSERT INTO table1(time,device_id,s1) values(2, 'd1', 2)",
-        "INSERT INTO table1(time,device_id,s2) values(3, 'd1', 3)",
-        "INSERT INTO table1(time,device_id,s1) values(4, 'd1', 4)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(5, 'd1', 5, 5)",
-        "INSERT INTO table1(time,device_id,s2) values(6, 'd1', 6)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(5000000000, 'd1', 
null, 7)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(5000000001, 'd1', 8, 
null)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(1, 'd2', 1, 1)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(2, 'd2', 2, 2)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(5000000000, 'd2', 
null, 3)",
-        "INSERT INTO table1(time,device_id,s1,s2) values(5000000001, 'd2', 4, 
null)",
+        "CREATE DATABASE root.db",
+        "CREATE TIMESERIES root.db.d1.s1 WITH DATATYPE=INT32, ENCODING=PLAIN",
+        "CREATE TIMESERIES root.db.d1.s2 WITH DATATYPE=FLOAT, ENCODING=PLAIN",
+        "INSERT INTO root.db.d1(timestamp,s1,s2) values(1, 1, 1)",
+        "INSERT INTO root.db.d1(timestamp,s1) values(2, 2)",
+        "INSERT INTO root.db.d1(timestamp,s2) values(3, 3)",
+        "INSERT INTO root.db.d1(timestamp,s1) values(4, 4)",
+        "INSERT INTO root.db.d1(timestamp,s1,s2) values(5, 5, 5)",
+        "INSERT INTO root.db.d1(timestamp,s2) values(6, 6)",
+        "INSERT INTO root.db.d1(timestamp,s1,s2) values(5000000000, null, 7)",
+        "INSERT INTO root.db.d1(timestamp,s1,s2) values(5000000001, 8, null)",
+        "CREATE TIMESERIES root.db.d2.s1 WITH DATATYPE=INT32, ENCODING=PLAIN",
+        "CREATE TIMESERIES root.db.d2.s2 WITH DATATYPE=FLOAT, ENCODING=PLAIN",
+        "INSERT INTO root.db.d2(timestamp,s1,s2) values(1, 1, 1)",
+        "INSERT INTO root.db.d2(timestamp,s1,s2) values(2, 2, 2)",
+        "INSERT INTO root.db.d2(timestamp,s1,s2) values(5000000000, null, 3)",
+        "INSERT INTO root.db.d2(timestamp,s1,s2) values(5000000001, 4, null)",
         "flush"
       };
 
@@ -67,19 +64,7 @@ public class IoTDBDiffFunctionIT {
   public static void setUp() throws Exception {
     
EnvFactory.getEnv().getConfig().getCommonConfig().setPartitionInterval(1000);
     EnvFactory.getEnv().initClusterEnvironment();
-    insertData();
-  }
-
-  protected static void insertData() {
-    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
-        Statement statement = connection.createStatement()) {
-
-      for (String sql : SQLs) {
-        statement.execute(sql);
-      }
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
+    prepareData(SQLs);
   }
 
   @AfterClass
@@ -89,141 +74,285 @@ public class IoTDBDiffFunctionIT {
 
   @Test
   public void testNewTransformerIgnoreNull() {
-    String[] expectedHeader = new String[] {"time", "_col1", "_col2"};
+    String[] expectedHeader =
+        new String[] {TIMESTAMP_STR, "Diff(root.db.d1.s1)", 
"diff(root.db.d1.s2)"};
     String[] retArray =
         new String[] {
-          "1997-01-01T08:00:00.001Z,null,null,",
-          "1997-01-01T08:00:00.002Z,1.0,null,",
-          "1997-01-01T08:00:00.003Z,null,2.0,",
-          "1997-01-01T08:00:00.004Z,2.0,null,",
-          "1997-01-01T08:00:00.005Z,1.0,2.0,",
-          "1997-01-01T08:00:00.006Z,null,1.0,",
-          "1970-02-27T20:53:20.000Z,null,1.0,",
-          "1970-02-27T20:53:20.001Z,3.0,null,"
+          "1,null,null,",
+          "2,1.0,null,",
+          "3,null,2.0,",
+          "4,2.0,null,",
+          "5,1.0,2.0,",
+          "6,null,1.0,",
+          "5000000000,null,1.0,",
+          "5000000001,3.0,null,"
         };
-    resultSetEqualTest(
-        "select time,diff(s1), diff(s2) from table1 where device_id='d1'",
-        expectedHeader,
-        retArray);
+    resultSetEqualTest("select Diff(s1), diff(s2) from root.db.d1", 
expectedHeader, retArray);
 
     // align by device
-    expectedHeader = new String[] {"time", "device_id", "_col1", "_col2"};
+    expectedHeader = new String[] {TIMESTAMP_STR, DEVICE, "Diff(s1)", 
"diff(s2)"};
     retArray =
         new String[] {
-          "1997-01-01T08:00:00.001Z,d1,null,null,",
-          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
-          "1997-01-01T08:00:00.003Z,d1,null,2.0,",
-          "1997-01-01T08:00:00.004Z,d1,2.0,null,",
-          "1997-01-01T08:00:00.005Z,d1,1.0,2.0,",
-          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.001Z,d1,3.0,null,",
-          "1997-01-01T08:00:00.001Z,d2,null,null",
-          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
-          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
-          "1970-02-27T20:53:20.001Z,d2,2.0,null,",
+          "1,root.db.d1,null,null,",
+          "2,root.db.d1,1.0,null,",
+          "3,root.db.d1,null,2.0,",
+          "4,root.db.d1,2.0,null,",
+          "5,root.db.d1,1.0,2.0,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000001,root.db.d1,3.0,null,",
+          "1,root.db.d2,null,null,",
+          "2,root.db.d2,1.0,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d2,2.0,null,"
         };
     resultSetEqualTest(
-        "select time, device_id, Diff(s1), diff(s2) from table1 where 
device_id='d1' or device_id='d2' order by device_id",
+        "select Diff(s1), diff(s2) from root.db.d1, root.db.d2 align by 
device",
         expectedHeader,
         retArray);
 
     // align by device + order by time
     retArray =
         new String[] {
-          "1997-01-01T08:00:00.001Z,d1,null,null,",
-          "1997-01-01T08:00:00.001Z,d2,null,null",
-          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
-          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
-          "1997-01-01T08:00:00.003Z,d1,null,2.0,",
-          "1997-01-01T08:00:00.004Z,d1,2.0,null,",
-          "1997-01-01T08:00:00.005Z,d1,1.0,2.0,",
-          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
-          "1970-02-27T20:53:20.001Z,d1,3.0,null,",
-          "1970-02-27T20:53:20.001Z,d2,2.0,null,",
+          "1,root.db.d1,null,null,",
+          "1,root.db.d2,null,null,",
+          "2,root.db.d1,1.0,null,",
+          "2,root.db.d2,1.0,1.0,",
+          "3,root.db.d1,null,2.0,",
+          "4,root.db.d1,2.0,null,",
+          "5,root.db.d1,1.0,2.0,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d1,3.0,null,",
+          "5000000001,root.db.d2,2.0,null,"
         };
     resultSetEqualTest(
-        "select time, device_id, Diff(s1), diff(s2) from table1 where 
device_id='d1' or device_id='d2' order by time,device_id",
+        "select Diff(s1), diff(s2) from root.db.d1, root.db.d2 order by time 
align by device",
         expectedHeader,
         retArray);
   }
 
   @Test
   public void testNewTransformerRespectNull() {
-    String[] expectedHeader = new String[] {"time", "_col1", "_col2"};
+    String[] expectedHeader =
+        new String[] {
+          TIMESTAMP_STR,
+          "Diff(root.db.d1.s1, \"ignoreNull\"=\"false\")",
+          "diff(root.db.d1.s2, \"ignoreNull\"=\"false\")"
+        };
     String[] retArray =
         new String[] {
-          "1997-01-01T08:00:00.001Z,null,null,",
-          "1997-01-01T08:00:00.002Z,1.0,null,",
-          "1997-01-01T08:00:00.003Z,null,null,",
-          "1997-01-01T08:00:00.004Z,null,null,",
-          "1997-01-01T08:00:00.005Z,1.0,null,",
-          "1997-01-01T08:00:00.006Z,null,1.0,",
-          "1970-02-27T20:53:20.000Z,null,1.0,",
-          "1970-02-27T20:53:20.001Z,null,null,"
+          "1,null,null,",
+          "2,1.0,null,",
+          "3,null,null,",
+          "4,null,null,",
+          "5,1.0,null,",
+          "6,null,1.0,",
+          "5000000000,null,1.0,",
+          "5000000001,null,null,"
         };
     resultSetEqualTest(
-        "select time, Diff(s1, false), diff(s2, false) from table1 where 
device_id='d1'",
+        "select Diff(s1, 'ignoreNull'='false'), diff(s2, 'ignoreNull'='false') 
from root.db.d1",
         expectedHeader,
         retArray);
 
     // align by device
-    expectedHeader = new String[] {"time", "device_id", "_col1", "_col2"};
+    expectedHeader =
+        new String[] {
+          TIMESTAMP_STR,
+          DEVICE,
+          "Diff(s1, \"ignoreNull\"=\"false\")",
+          "diff(s2, \"ignoreNull\"=\"false\")"
+        };
     retArray =
         new String[] {
-          "1997-01-01T08:00:00.001Z,d1,null,null,",
-          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
-          "1997-01-01T08:00:00.003Z,d1,null,null,",
-          "1997-01-01T08:00:00.004Z,d1,null,null,",
-          "1997-01-01T08:00:00.005Z,d1,1.0,null,",
-          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.001Z,d1,null,null,",
-          "1997-01-01T08:00:00.001Z,d2,null,null",
-          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
-          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
-          "1970-02-27T20:53:20.001Z,d2,null,null,",
+          "1,root.db.d1,null,null,",
+          "2,root.db.d1,1.0,null,",
+          "3,root.db.d1,null,null,",
+          "4,root.db.d1,null,null,",
+          "5,root.db.d1,1.0,null,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000001,root.db.d1,null,null,",
+          "1,root.db.d2,null,null,",
+          "2,root.db.d2,1.0,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d2,null,null,",
         };
     resultSetEqualTest(
-        "select time, device_id, Diff(s1, false), diff(s2, false) from table1 
where device_id='d1' or device_id='d2' order by device_id",
+        "select Diff(s1, 'ignoreNull'='false'), diff(s2, 'ignoreNull'='false') 
from root.db.d1, root.db.d2 align by device",
         expectedHeader,
         retArray);
 
     // align by device + order by time
     retArray =
         new String[] {
-          "1997-01-01T08:00:00.001Z,d1,null,null,",
-          "1997-01-01T08:00:00.001Z,d2,null,null",
-          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
-          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
-          "1997-01-01T08:00:00.003Z,d1,null,null,",
-          "1997-01-01T08:00:00.004Z,d1,null,null,",
-          "1997-01-01T08:00:00.005Z,d1,1.0,null,",
-          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
-          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
-          "1970-02-27T20:53:20.001Z,d1,null,null,",
-          "1970-02-27T20:53:20.001Z,d2,null,null,",
+          "1,root.db.d1,null,null,",
+          "1,root.db.d2,null,null,",
+          "2,root.db.d1,1.0,null,",
+          "2,root.db.d2,1.0,1.0,",
+          "3,root.db.d1,null,null,",
+          "4,root.db.d1,null,null,",
+          "5,root.db.d1,1.0,null,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d1,null,null,",
+          "5000000001,root.db.d2,null,null,",
         };
     resultSetEqualTest(
-        "select time, device_id, Diff(s1, false), diff(s2, false) where 
device_id='d1' or device_id='d2' order by time,device_id",
+        "select Diff(s1, 'ignoreNull'='false'), diff(s2, 'ignoreNull'='false') 
from root.db.d1, root.db.d2 order by time align by device",
         expectedHeader,
         retArray);
   }
 
+  // [change_points] is not mappable function, so this calculation use old 
transformer
   @Test
-  public void testCaseInSensitive() {
-    String[] expectedHeader = new String[] {"time", "s1", "s2"};
+  public void testOldTransformerIgnoreNull() {
+    String[] expectedHeader =
+        new String[] {TIMESTAMP_STR, "change_points(root.db.d1.s1)", 
"diff(root.db.d1.s2)"};
+    String[] retArray =
+        new String[] {
+          "1,1,null,",
+          "2,2,null,",
+          "3,null,2.0,",
+          "4,4,null,",
+          "5,5,2.0,",
+          "6,null,1.0,",
+          "5000000000,null,1.0,",
+          "5000000001,8,null,"
+        };
+    resultSetEqualTest(
+        "select change_points(s1), diff(s2) from root.db.d1", expectedHeader, 
retArray);
+
+    // align by device
+    expectedHeader = new String[] {TIMESTAMP_STR, DEVICE, "change_points(s1)", 
"diff(s2)"};
+    retArray =
+        new String[] {
+          "1,root.db.d1,1,null,",
+          "2,root.db.d1,2,null,",
+          "3,root.db.d1,null,2.0,",
+          "4,root.db.d1,4,null,",
+          "5,root.db.d1,5,2.0,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000001,root.db.d1,8,null,",
+          "1,root.db.d2,1,null,",
+          "2,root.db.d2,2,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d2,4,null,",
+        };
+    resultSetEqualTest(
+        "select change_points(s1), diff(s2) from root.db.d1, root.db.d2 align 
by device",
+        expectedHeader,
+        retArray);
+
+    // align by device + order by time
+    expectedHeader = new String[] {TIMESTAMP_STR, DEVICE, "change_points(s1)", 
"diff(s2)"};
+    retArray =
+        new String[] {
+          "1,root.db.d1,1,null,",
+          "1,root.db.d2,1,null,",
+          "2,root.db.d1,2,null,",
+          "2,root.db.d2,2,1.0,",
+          "3,root.db.d1,null,2.0,",
+          "4,root.db.d1,4,null,",
+          "5,root.db.d1,5,2.0,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d1,8,null,",
+          "5000000001,root.db.d2,4,null,",
+        };
+    resultSetEqualTest(
+        "select change_points(s1), diff(s2) from root.db.d1, root.db.d2 order 
by time align by device",
+        expectedHeader,
+        retArray);
+  }
+
+  @Test
+  public void testOldTransformerRespectNull() {
+    String[] expectedHeader =
+        new String[] {
+          TIMESTAMP_STR,
+          "change_points(root.db.d1.s1)",
+          "diff(root.db.d1.s2, \"ignoreNull\"=\"false\")"
+        };
     String[] retArray =
         new String[] {
-          "1997-01-01T08:00:00.002Z,2,null,",
-          "1997-01-01T08:00:00.004Z,4,null,",
-          "1997-01-01T08:00:00.005Z,5,5.0,"
+          "1,1,null,",
+          "2,2,null,",
+          "4,4,null,",
+          "5,5,null,",
+          "6,null,1.0,",
+          "5000000000,null,1.0,",
+          "5000000001,8,null,"
+        };
+    resultSetEqualTest(
+        "select change_points(s1), diff(s2, 'ignoreNull'='false') from 
root.db.d1",
+        expectedHeader,
+        retArray);
+
+    // align by device
+    expectedHeader =
+        new String[] {
+          TIMESTAMP_STR, DEVICE, "change_points(s1)", "diff(s2, 
\"ignoreNull\"=\"false\")"
+        };
+    retArray =
+        new String[] {
+          "1,root.db.d1,1,null,",
+          "2,root.db.d1,2,null,",
+          "4,root.db.d1,4,null,",
+          "5,root.db.d1,5,null,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000001,root.db.d1,8,null,",
+          "1,root.db.d2,1,null,",
+          "2,root.db.d2,2,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d2,4,null,",
+        };
+    resultSetEqualTest(
+        "select change_points(s1), diff(s2, 'ignoreNull'='false') from 
root.db.d1, root.db.d2 align by device",
+        expectedHeader,
+        retArray);
+
+    // align by device + order by time
+    expectedHeader =
+        new String[] {
+          TIMESTAMP_STR, DEVICE, "change_points(s1)", "diff(s2, 
\"ignoreNull\"=\"false\")"
         };
+    retArray =
+        new String[] {
+          "1,root.db.d1,1,null,",
+          "1,root.db.d2,1,null,",
+          "2,root.db.d1,2,null,",
+          "2,root.db.d2,2,1.0,",
+          "4,root.db.d1,4,null,",
+          "5,root.db.d1,5,null,",
+          "6,root.db.d1,null,1.0,",
+          "5000000000,root.db.d1,null,1.0,",
+          "5000000000,root.db.d2,null,1.0,",
+          "5000000001,root.db.d1,8,null,",
+          "5000000001,root.db.d2,4,null,",
+        };
+    resultSetEqualTest(
+        "select change_points(s1), diff(s2, 'ignoreNull'='false') from 
root.db.d1, root.db.d2 order by time align by device",
+        expectedHeader,
+        retArray);
+  }
+
+  @Test
+  public void testCaseInSensitive() {
+    String[] expectedHeader = new String[] {TIMESTAMP_STR, "root.db.d1.s1", 
"root.db.d1.s2"};
+    String[] retArray = new String[] {"2,2,null,", "4,4,null,", "5,5,5.0,"};
+    resultSetEqualTest(
+        "select s1, s2 from root.db.d1 where Diff(s1) between 1 and 2", 
expectedHeader, retArray);
+
+    retArray = new String[] {};
     resultSetEqualTest(
-        "select time, s1, s2 from table1 where device_id='d1' and diff(s1) 
between 1 and 2",
+        "select s1, s2 from root.db.d1 where Diff(notExist) between 1 and 2",
         expectedHeader,
         retArray);
   }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBDatetimeFormatIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBDatetimeFormatIT.java
new file mode 100644
index 00000000000..bf237caa66d
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBDatetimeFormatIT.java
@@ -0,0 +1,157 @@
+/*
+ * 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.relational.it.query.old;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBDatetimeFormatIT {
+
+  private static final String DATABASE_NAME = "db";
+
+  @BeforeClass
+  public void setUp() throws Exception {
+    
EnvFactory.getEnv().getConfig().getCommonConfig().setTimestampPrecisionCheckEnabled(false);
+    EnvFactory.getEnv().initClusterEnvironment();
+
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      statement.execute("create database " + DATABASE_NAME);
+      statement.execute("use " + DATABASE_NAME);
+      statement.execute(
+          "create table table1(device_id STRING ID, s1 INT32 MEASUREMENT, s2 
DOUBLE MEASUREMENT);");
+    }
+  }
+
+  @AfterClass
+  public void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  @Test
+  public void testDatetimeInputFormat() {
+    String[] datetimeStrings = {
+      "2022-01-01 01:02:03", // yyyy-MM-dd HH:mm:ss
+      "2022/01/02 01:02:03", // yyyy/MM/dd HH:mm:ss
+      "2022.01.03 01:02:03", // yyyy.MM.dd HH:mm:ss
+      "2022-01-04 01:02:03+01:00", // yyyy-MM-dd HH:mm:ssZZ
+      "2022/01/05 01:02:03+01:00", // yyyy/MM/dd HH:mm:ssZZ
+      "2022.01.06 01:02:03+01:00", // yyyy.MM.dd HH:mm:ssZZ
+      "2022-01-07 01:02:03.400", // yyyy-MM-dd HH:mm:ss.SSS
+      "2022/01/08 01:02:03.400", // yyyy/MM/dd HH:mm:ss.SSS
+      "2022.01.09 01:02:03.400", // yyyy.MM.dd HH:mm:ss.SSS
+      "2022-01-10 01:02:03.400+01:00", // yyyy-MM-dd HH:mm:ss.SSSZZ
+      "2022-01-11 01:02:03.400+01:00", // yyyy/MM/dd HH:mm:ss.SSSZZ
+      "2022-01-12 01:02:03.400+01:00", // yyyy.MM.dd HH:mm:ss.SSSZZ
+      "2022-01-13T01:02:03.400+01:00" // ISO8601 standard time format
+    };
+    long[] timestamps = {
+      1640970123000L,
+      1641056523000L,
+      1641142923000L,
+      1641254523000L,
+      1641340923000L,
+      1641427323000L,
+      1641488523400L,
+      1641574923400L,
+      1641661323400L,
+      1641772923400L,
+      1641859323400L,
+      1641945723400L,
+      1642032123400L
+    };
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      connection.setClientInfo("time_zone", "+08:00");
+      statement.execute("use " + DATABASE_NAME);
+
+      for (int i = 0; i < datetimeStrings.length; i++) {
+        String insertSql =
+            String.format(
+                "INSERT INTO table1(time, device_id, s1) values (%s, %s, %d)",
+                datetimeStrings[i], "d1", i);
+        statement.execute(insertSql);
+      }
+
+      try (ResultSet resultSet =
+          statement.executeQuery("SELECT time, s1 FROM table1 where 
device_id='d1'")) {
+        Assert.assertNotNull(resultSet);
+        int cnt = 0;
+        while (resultSet.next()) {
+          Assert.assertEquals(timestamps[cnt], resultSet.getLong(1));
+          cnt++;
+        }
+        Assert.assertEquals(timestamps.length, cnt);
+      }
+
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail();
+    }
+  }
+
+  @Test
+  public void testBigDateTime() {
+
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      statement.execute("use " + DATABASE_NAME);
+
+      statement.execute(
+          "insert into table1(time,device_id,s2) values (1618283005586000, 
'd1',8.76);");
+
+      try (ResultSet resultSet =
+          statement.executeQuery(
+              "select time, s2 from table1 where device_id='d1' and 
time=53251-05-07T17:06:26.000+08:00")) {
+        Assert.assertNotNull(resultSet);
+        int cnt = 0;
+        while (resultSet.next()) {
+          Assert.assertEquals(1618283005586000L, resultSet.getLong(1));
+          cnt++;
+        }
+        Assert.assertEquals(1, cnt);
+      }
+
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail();
+    }
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryIT.java
new file mode 100644
index 00000000000..629579747f0
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryIT.java
@@ -0,0 +1,460 @@
+/*
+ * 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.relational.it.query.old;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBNestedQueryIT {
+
+  private static final String DATABASE_NAME = "db";
+
+  protected static final int ITERATION_TIMES = 10;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    EnvFactory.getEnv()
+        .getConfig()
+        .getCommonConfig()
+        .setEnableSeqSpaceCompaction(false)
+        .setEnableUnseqSpaceCompaction(false)
+        .setEnableCrossSpaceCompaction(false)
+        .setUdfMemoryBudgetInMB(5);
+
+    EnvFactory.getEnv().initClusterEnvironment();
+    createTable();
+    generateData();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  private static void createTable() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      statement.execute("CREATE DATABASE " + DATABASE_NAME);
+      statement.execute("USE " + DATABASE_NAME);
+      statement.execute(
+          "create table vehicle1(device_id STRING ID, s1 INT32 MEASUREMENT, s2 
INT32 MEASUREMENT, s3 TEXT MEASUREMENT, s4 STRING MEASUREMENT, s5 DATE 
MEASUREMENT, s6 TIMESTAMP MEASUREMENT);");
+
+      statement.execute(
+          "create table vehicle2(device_id STRING ID, s1 FLOAT MEASUREMENT, s2 
DOUBLE MEASUREMENT, empty DOUBLE MEASUREMENT");
+    } catch (SQLException throwable) {
+      fail(throwable.getMessage());
+    }
+  }
+
+  private static void generateData() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      statement.execute("USE " + DATABASE_NAME);
+      for (int i = 1; i <= ITERATION_TIMES; ++i) {
+        statement.execute(
+            String.format(
+                "insert into vehicle1(time,device_id,s1,s2,s3,s4,s6) 
values(%d,%s%d,%d,%s,%s,%d)",
+                i, "d1", i, i, i, i, i));
+        statement.execute(
+            (String.format(
+                "insert into vehicle2(time,device_id,s1,s2) 
values(%d,%s,%d,%d)", i, "d2", i, i)));
+      }
+      statement.execute("insert into vehicle1(timestamp,s5) values(1, 'd1', 
'2024-01-01')");
+      statement.execute("insert into vehicle1(timestamp,s5) values(2, 
'd1','2024-01-02')");
+      statement.execute("insert into vehicle1(timestamp,s5) values(3, 
'd1','2024-01-03')");
+    } catch (SQLException throwable) {
+      fail(throwable.getMessage());
+    }
+  }
+
+  @Ignore
+  @Test
+  public void testNestedRowByRowUDFExpressions() {
+    String sqlStr =
+        "select time, s1, s2, sin(sin(s1) * sin(s2) + cos(s1) * cos(s1)) + 
sin(sin(s1 - s1 + s2) * sin(s2) + cos(s1) * cos(s1)), asin(sin(asin(sin(s1 - s2 
/ (-s1))))) from vehicle2";
+
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      ResultSet resultSet = statement.executeQuery(sqlStr);
+
+      assertEquals(1 + 4, resultSet.getMetaData().getColumnCount());
+
+      int count = 0;
+      while (resultSet.next()) {
+        ++count;
+
+        assertEquals(count, resultSet.getLong(1));
+        assertEquals(count, Double.parseDouble(resultSet.getString(2)), 0);
+        assertEquals(count, Double.parseDouble(resultSet.getString(3)), 0);
+        assertEquals(2 * Math.sin(1.0), 
Double.parseDouble(resultSet.getString(4)), 1e-5);
+        assertEquals(
+            Math.asin(Math.sin(Math.asin(Math.sin(count - count / (-count))))),
+            Double.parseDouble(resultSet.getString(5)),
+            1e-5);
+      }
+
+      assertEquals(ITERATION_TIMES, count);
+    } catch (SQLException throwable) {
+      fail(throwable.getMessage());
+    }
+  }
+
+  @Test
+  public void testRawDataQueryWithConstants() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      String query = "SELECT time, 1 + s1 FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(i + 1.0D, rs.getDouble(2), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+
+      query = "SELECT time, (1 + 4) * 2 / 10 + s1 FROM vehicle1 where 
device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(i + 1.0D, rs.getDouble(2), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testDuplicatedRawDataQueryWithConstants() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      String query = "SELECT time, 1 + s1, 1 + s1 FROM vehicle1 where 
device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(i + 1.0D, rs.getDouble(2), 0.01);
+          Assert.assertEquals(i + 1.0D, rs.getDouble(3), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testCommutativeLaws() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      String query =
+          "SELECT time, s1, s1 + 1, 1 + s1, s1 * 2, 2 * s1 FROM vehicle1 where 
device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(i, rs.getInt(2));
+          Assert.assertEquals(i + 1.0D, rs.getDouble(3), 0.01);
+          Assert.assertEquals(i + 1.0D, rs.getDouble(4), 0.01);
+          Assert.assertEquals(i * 2.0D, rs.getDouble(5), 0.01);
+          Assert.assertEquals(i * 2.0D, rs.getDouble(6), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testAssociativeLaws() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      String query =
+          "SELECT time, s1, s1 + 1 + 2, (s1 + 1) + 2, s1 + (1 + 2), s1 * 2 * 
3, s1 * (2 * 3), (s1 * 2) * 3 FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(i, rs.getInt(2));
+          Assert.assertEquals(i + 3.0D, rs.getDouble(3), 0.01);
+          Assert.assertEquals(i + 3.0D, rs.getDouble(4), 0.01);
+          Assert.assertEquals(i + 3.0D, rs.getDouble(5), 0.01);
+          Assert.assertEquals(i * 6.0D, rs.getDouble(6), 0.01);
+          Assert.assertEquals(i * 6.0D, rs.getDouble(7), 0.01);
+          Assert.assertEquals(i * 6.0D, rs.getDouble(8), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testDistributiveLaw() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      String query =
+          "SELECT time, s1, (s1 + 1) * 2, s1 * 2 + 1 * 2, (s1 + 1) / 2, s1 / 2 
+ 1 / 2 FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(i, rs.getInt(2));
+          Assert.assertEquals(2 * i + 2.0D, rs.getDouble(3), 0.01);
+          Assert.assertEquals(2 * i + 2.0D, rs.getDouble(4), 0.01);
+          Assert.assertEquals(i / 2.0D + 0.5D, rs.getDouble(5), 0.01);
+          Assert.assertEquals(i / 2.0D + 0.5D, rs.getDouble(6), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testOrderOfArithmeticOperations() {
+    // Priority from high to low:
+    //   1. exponentiation and root extraction (not supported yet)
+    //   2. multiplication and division
+    //   3. addition and subtraction
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      String query =
+          "SELECT time, 1 + s1 * 2 + 1, (1 + s1) * 2 + 1, (1 + s1) * (2 + 1)  
FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(2 * i + 2.0D, rs.getDouble(2), 0.01);
+          Assert.assertEquals(2 * i + 3.0D, rs.getDouble(3), 0.01);
+          Assert.assertEquals(3 * i + 3.0D, rs.getDouble(4), 0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+
+      query =
+          "SELECT time, 1 - s1 / 2 + 1, (1 - s1) / 2 + 1, (1 - s1) / (2 + 1)  
FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+          Assert.assertEquals(2.0D - i / 2.0D, rs.getDouble(2), 0.01);
+          Assert.assertEquals(1.5 - i / 2.0D, rs.getDouble(3), 0.01);
+          Assert.assertEquals((1.0D / 3.0D) * (1.0D - i), rs.getDouble(4), 
0.01);
+        }
+        Assert.assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testBetweenExpression() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      int start = 2, end = 8;
+      String query =
+          "SELECT * FROM vehicle1 where device_id='d1' WHERE s1 BETWEEN " + 
start + " AND " + end;
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = start; i <= end; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(String.valueOf(i), rs.getString("time"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s1"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s2"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s3"));
+        }
+      }
+
+      query =
+          "SELECT * FROM vehicle1 where device_id='d1' WHERE s1 NOT BETWEEN " 
// test not between
+              + (end + 1)
+              + " AND "
+              + ITERATION_TIMES;
+      try (ResultSet rs = statement.executeQuery(query)) {
+        Assert.assertTrue(rs.next());
+        Assert.assertEquals("1", rs.getString("time"));
+        Assert.assertEquals("1", rs.getString("s1"));
+        Assert.assertEquals("1", rs.getString("s2"));
+        Assert.assertEquals("1", rs.getString("s3"));
+        for (int i = start; i <= end; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(String.valueOf(i), rs.getString("time"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s1"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s2"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s3"));
+        }
+      }
+
+      query =
+          "SELECT * FROM vehicle1 where device_id='d1' WHERE time BETWEEN " + 
start + " AND " + end;
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = start; i <= end; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(String.valueOf(i), rs.getString("time"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s1"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s2"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s3"));
+        }
+      }
+
+      query =
+          "SELECT * FROM vehicle1 where device_id='d1' WHERE time NOT BETWEEN 
" // test not between
+              + (end + 1)
+              + " AND "
+              + ITERATION_TIMES;
+      try (ResultSet rs = statement.executeQuery(query)) {
+        Assert.assertTrue(rs.next());
+        Assert.assertEquals("1", rs.getString("time"));
+        Assert.assertEquals("1", rs.getString("s1"));
+        Assert.assertEquals("1", rs.getString("s2"));
+        Assert.assertEquals("1", rs.getString("s3"));
+        for (int i = start; i <= end; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(String.valueOf(i), rs.getString("time"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s1"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s2"));
+          Assert.assertEquals(String.valueOf(i), rs.getString("s3"));
+        }
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testRegularLikeInExpressions() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      //      String query =
+      //          "SELECT s1 FROM vehicle1 where device_id='d1' WHERE s3 LIKE 
'_' && s3 REGEXP
+      // '[0-9]' && s3 IN ('4', '2', '3')";
+      //      try (ResultSet rs = statement.executeQuery(query)) {
+      //        for (int i = 2; i <= 4; i++) {
+      //          Assert.assertTrue(rs.next());
+      //          Assert.assertEquals(i, rs.getLong(1));
+      //        }
+      //        Assert.assertFalse(rs.next());
+      //      }
+
+      //      String query2 =
+      //          "SELECT s1 FROM vehicle1 where device_id='d1' WHERE s4 LIKE 
'_' && s4 REGEXP
+      // '[0-9]' && s4 IN ('4', '2', '3')";
+      //      try (ResultSet rs = statement.executeQuery(query2)) {
+      //        for (int i = 2; i <= 4; i++) {
+      //          Assert.assertTrue(rs.next());
+      //          Assert.assertEquals(i, rs.getLong(1));
+      //        }
+      //        Assert.assertFalse(rs.next());
+      //      }
+
+      String query3 =
+          "SELECT time,s1 FROM vehicle1 where device_id='d1' WHERE s5 IN 
('2024-01-01', '2024-01-02', '2024-01-03')";
+      try (ResultSet rs = statement.executeQuery(query3)) {
+        for (int i = 1; i <= 3; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+        }
+        Assert.assertFalse(rs.next());
+      }
+
+      String query4 = "SELECT time,s1 FROM vehicle1 where device_id='d1' WHERE 
s6 IN (1, 2, 3)";
+      try (ResultSet rs = statement.executeQuery(query4)) {
+        for (int i = 1; i <= 3; i++) {
+          Assert.assertTrue(rs.next());
+          Assert.assertEquals(i, rs.getLong(1));
+        }
+        Assert.assertFalse(rs.next());
+      }
+
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void testTimeExpressions() {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      String query =
+          "SELECT s1, time, time, -(-time), time + 1 - 1, time + s1 - s1, time 
+ 1 - 1 FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        for (int i = 1; i <= ITERATION_TIMES; ++i) {
+          assertTrue(rs.next());
+          for (int j = 1; j <= 7; ++j) {
+            assertEquals(i, Double.parseDouble(rs.getString(j)), 0.001);
+          }
+        }
+        assertFalse(rs.next());
+      }
+
+      query = "SELECT time, 2 * time FROM vehicle1 where device_id='d1'";
+      try (ResultSet rs = statement.executeQuery(query)) {
+        assertFalse(rs.next());
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionIT.java
index 9da3963c5da..4cc357351aa 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBDiffFunctionIT.java
@@ -35,31 +35,31 @@ import java.sql.Connection;
 import java.sql.Statement;
 
 import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest;
-import static org.apache.iotdb.itbase.constant.TestConstant.DEVICE;
-import static org.apache.iotdb.itbase.constant.TestConstant.TIMESTAMP_STR;
 
 @RunWith(IoTDBTestRunner.class)
 @Category({LocalStandaloneIT.class, ClusterIT.class})
 public class IoTDBDiffFunctionIT {
+
+  private static final String DATABASE_NAME = "db";
+
+  // 2 devices 4 regions
   protected static final String[] SQLs =
       new String[] {
-        "CREATE DATABASE root.db",
-        "CREATE TIMESERIES root.db.d1.s1 WITH DATATYPE=INT32, ENCODING=PLAIN",
-        "CREATE TIMESERIES root.db.d1.s2 WITH DATATYPE=FLOAT, ENCODING=PLAIN",
-        "INSERT INTO root.db.d1(timestamp,s1,s2) values(1, 1, 1)",
-        "INSERT INTO root.db.d1(timestamp,s1) values(2, 2)",
-        "INSERT INTO root.db.d1(timestamp,s2) values(3, 3)",
-        "INSERT INTO root.db.d1(timestamp,s1) values(4, 4)",
-        "INSERT INTO root.db.d1(timestamp,s1,s2) values(5, 5, 5)",
-        "INSERT INTO root.db.d1(timestamp,s2) values(6, 6)",
-        "INSERT INTO root.db.d1(timestamp,s1,s2) values(5000000000, null, 7)",
-        "INSERT INTO root.db.d1(timestamp,s1,s2) values(5000000001, 8, null)",
-        "CREATE TIMESERIES root.db.d2.s1 WITH DATATYPE=INT32, ENCODING=PLAIN",
-        "CREATE TIMESERIES root.db.d2.s2 WITH DATATYPE=FLOAT, ENCODING=PLAIN",
-        "INSERT INTO root.db.d2(timestamp,s1,s2) values(1, 1, 1)",
-        "INSERT INTO root.db.d2(timestamp,s1,s2) values(2, 2, 2)",
-        "INSERT INTO root.db.d2(timestamp,s1,s2) values(5000000000, null, 3)",
-        "INSERT INTO root.db.d2(timestamp,s1,s2) values(5000000001, 4, null)",
+        "CREATE DATABASE " + DATABASE_NAME,
+        "use " + DATABASE_NAME,
+        "create table table1(device_id STRING ID, s1 INT32 MEASUREMENT, s2 
INT32 MEASUREMENT);",
+        "INSERT INTO table1(time,device_id,s1,s2) values(1, 'd1', 1, 1)",
+        "INSERT INTO table1(time,device_id,s1) values(2, 'd1', 2)",
+        "INSERT INTO table1(time,device_id,s2) values(3, 'd1', 3)",
+        "INSERT INTO table1(time,device_id,s1) values(4, 'd1', 4)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(5, 'd1', 5, 5)",
+        "INSERT INTO table1(time,device_id,s2) values(6, 'd1', 6)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(5000000000, 'd1', 
null, 7)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(5000000001, 'd1', 8, 
null)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(1, 'd2', 1, 1)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(2, 'd2', 2, 2)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(5000000000, 'd2', 
null, 3)",
+        "INSERT INTO table1(time,device_id,s1,s2) values(5000000001, 'd2', 4, 
null)",
         "flush"
       };
 
@@ -89,285 +89,141 @@ public class IoTDBDiffFunctionIT {
 
   @Test
   public void testNewTransformerIgnoreNull() {
-    String[] expectedHeader =
-        new String[] {TIMESTAMP_STR, "Diff(root.db.d1.s1)", 
"diff(root.db.d1.s2)"};
-    String[] retArray =
-        new String[] {
-          "1,null,null,",
-          "2,1.0,null,",
-          "3,null,2.0,",
-          "4,2.0,null,",
-          "5,1.0,2.0,",
-          "6,null,1.0,",
-          "5000000000,null,1.0,",
-          "5000000001,3.0,null,"
-        };
-    resultSetEqualTest("select Diff(s1), diff(s2) from root.db.d1", 
expectedHeader, retArray);
-
-    // align by device
-    expectedHeader = new String[] {TIMESTAMP_STR, DEVICE, "Diff(s1)", 
"diff(s2)"};
-    retArray =
-        new String[] {
-          "1,root.db.d1,null,null,",
-          "2,root.db.d1,1.0,null,",
-          "3,root.db.d1,null,2.0,",
-          "4,root.db.d1,2.0,null,",
-          "5,root.db.d1,1.0,2.0,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000001,root.db.d1,3.0,null,",
-          "1,root.db.d2,null,null,",
-          "2,root.db.d2,1.0,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d2,2.0,null,"
-        };
-    resultSetEqualTest(
-        "select Diff(s1), diff(s2) from root.db.d1, root.db.d2 align by 
device",
-        expectedHeader,
-        retArray);
-
-    // align by device + order by time
-    retArray =
-        new String[] {
-          "1,root.db.d1,null,null,",
-          "1,root.db.d2,null,null,",
-          "2,root.db.d1,1.0,null,",
-          "2,root.db.d2,1.0,1.0,",
-          "3,root.db.d1,null,2.0,",
-          "4,root.db.d1,2.0,null,",
-          "5,root.db.d1,1.0,2.0,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d1,3.0,null,",
-          "5000000001,root.db.d2,2.0,null,"
-        };
-    resultSetEqualTest(
-        "select Diff(s1), diff(s2) from root.db.d1, root.db.d2 order by time 
align by device",
-        expectedHeader,
-        retArray);
-  }
-
-  @Test
-  public void testNewTransformerRespectNull() {
-    String[] expectedHeader =
-        new String[] {
-          TIMESTAMP_STR,
-          "Diff(root.db.d1.s1, \"ignoreNull\"=\"false\")",
-          "diff(root.db.d1.s2, \"ignoreNull\"=\"false\")"
-        };
+    String[] expectedHeader = new String[] {"time", "_col1", "_col2"};
     String[] retArray =
         new String[] {
-          "1,null,null,",
-          "2,1.0,null,",
-          "3,null,null,",
-          "4,null,null,",
-          "5,1.0,null,",
-          "6,null,1.0,",
-          "5000000000,null,1.0,",
-          "5000000001,null,null,"
-        };
-    resultSetEqualTest(
-        "select Diff(s1, 'ignoreNull'='false'), diff(s2, 'ignoreNull'='false') 
from root.db.d1",
-        expectedHeader,
-        retArray);
-
-    // align by device
-    expectedHeader =
-        new String[] {
-          TIMESTAMP_STR,
-          DEVICE,
-          "Diff(s1, \"ignoreNull\"=\"false\")",
-          "diff(s2, \"ignoreNull\"=\"false\")"
-        };
-    retArray =
-        new String[] {
-          "1,root.db.d1,null,null,",
-          "2,root.db.d1,1.0,null,",
-          "3,root.db.d1,null,null,",
-          "4,root.db.d1,null,null,",
-          "5,root.db.d1,1.0,null,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000001,root.db.d1,null,null,",
-          "1,root.db.d2,null,null,",
-          "2,root.db.d2,1.0,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d2,null,null,",
-        };
-    resultSetEqualTest(
-        "select Diff(s1, 'ignoreNull'='false'), diff(s2, 'ignoreNull'='false') 
from root.db.d1, root.db.d2 align by device",
-        expectedHeader,
-        retArray);
-
-    // align by device + order by time
-    retArray =
-        new String[] {
-          "1,root.db.d1,null,null,",
-          "1,root.db.d2,null,null,",
-          "2,root.db.d1,1.0,null,",
-          "2,root.db.d2,1.0,1.0,",
-          "3,root.db.d1,null,null,",
-          "4,root.db.d1,null,null,",
-          "5,root.db.d1,1.0,null,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d1,null,null,",
-          "5000000001,root.db.d2,null,null,",
+          "1997-01-01T08:00:00.001Z,null,null,",
+          "1997-01-01T08:00:00.002Z,1.0,null,",
+          "1997-01-01T08:00:00.003Z,null,2.0,",
+          "1997-01-01T08:00:00.004Z,2.0,null,",
+          "1997-01-01T08:00:00.005Z,1.0,2.0,",
+          "1997-01-01T08:00:00.006Z,null,1.0,",
+          "1970-02-27T20:53:20.000Z,null,1.0,",
+          "1970-02-27T20:53:20.001Z,3.0,null,"
         };
     resultSetEqualTest(
-        "select Diff(s1, 'ignoreNull'='false'), diff(s2, 'ignoreNull'='false') 
from root.db.d1, root.db.d2 order by time align by device",
+        "select time,diff(s1), diff(s2) from table1 where device_id='d1'",
         expectedHeader,
         retArray);
-  }
-
-  // [change_points] is not mappable function, so this calculation use old 
transformer
-  @Test
-  public void testOldTransformerIgnoreNull() {
-    String[] expectedHeader =
-        new String[] {TIMESTAMP_STR, "change_points(root.db.d1.s1)", 
"diff(root.db.d1.s2)"};
-    String[] retArray =
-        new String[] {
-          "1,1,null,",
-          "2,2,null,",
-          "3,null,2.0,",
-          "4,4,null,",
-          "5,5,2.0,",
-          "6,null,1.0,",
-          "5000000000,null,1.0,",
-          "5000000001,8,null,"
-        };
-    resultSetEqualTest(
-        "select change_points(s1), diff(s2) from root.db.d1", expectedHeader, 
retArray);
 
     // align by device
-    expectedHeader = new String[] {TIMESTAMP_STR, DEVICE, "change_points(s1)", 
"diff(s2)"};
+    expectedHeader = new String[] {"time", "device_id", "_col1", "_col2"};
     retArray =
         new String[] {
-          "1,root.db.d1,1,null,",
-          "2,root.db.d1,2,null,",
-          "3,root.db.d1,null,2.0,",
-          "4,root.db.d1,4,null,",
-          "5,root.db.d1,5,2.0,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000001,root.db.d1,8,null,",
-          "1,root.db.d2,1,null,",
-          "2,root.db.d2,2,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d2,4,null,",
+          "1997-01-01T08:00:00.001Z,d1,null,null,",
+          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
+          "1997-01-01T08:00:00.003Z,d1,null,2.0,",
+          "1997-01-01T08:00:00.004Z,d1,2.0,null,",
+          "1997-01-01T08:00:00.005Z,d1,1.0,2.0,",
+          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.001Z,d1,3.0,null,",
+          "1997-01-01T08:00:00.001Z,d2,-7.0,-6.0",
+          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
+          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
+          "1970-02-27T20:53:20.001Z,d2,2.0,null,",
         };
     resultSetEqualTest(
-        "select change_points(s1), diff(s2) from root.db.d1, root.db.d2 align 
by device",
+        "select time, device_id, Diff(s1), diff(s2) from table1 where 
device_id='d1' or device_id='d2' order by device_id",
         expectedHeader,
         retArray);
 
     // align by device + order by time
-    expectedHeader = new String[] {TIMESTAMP_STR, DEVICE, "change_points(s1)", 
"diff(s2)"};
     retArray =
         new String[] {
-          "1,root.db.d1,1,null,",
-          "1,root.db.d2,1,null,",
-          "2,root.db.d1,2,null,",
-          "2,root.db.d2,2,1.0,",
-          "3,root.db.d1,null,2.0,",
-          "4,root.db.d1,4,null,",
-          "5,root.db.d1,5,2.0,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d1,8,null,",
-          "5000000001,root.db.d2,4,null,",
+          "1997-01-01T08:00:00.001Z,d1,null,null,",
+          "1997-01-01T08:00:00.001Z,d2,null,null",
+          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
+          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
+          "1997-01-01T08:00:00.003Z,d1,null,2.0,",
+          "1997-01-01T08:00:00.004Z,d1,2.0,null,",
+          "1997-01-01T08:00:00.005Z,d1,1.0,2.0,",
+          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
+          "1970-02-27T20:53:20.001Z,d1,3.0,null,",
+          "1970-02-27T20:53:20.001Z,d2,2.0,null,",
         };
     resultSetEqualTest(
-        "select change_points(s1), diff(s2) from root.db.d1, root.db.d2 order 
by time align by device",
+        "select time, device_id, Diff(s1), diff(s2) from table1 where 
device_id='d1' or device_id='d2' order by time,device_id",
         expectedHeader,
         retArray);
   }
 
   @Test
-  public void testOldTransformerRespectNull() {
-    String[] expectedHeader =
-        new String[] {
-          TIMESTAMP_STR,
-          "change_points(root.db.d1.s1)",
-          "diff(root.db.d1.s2, \"ignoreNull\"=\"false\")"
-        };
+  public void testNewTransformerRespectNull() {
+    String[] expectedHeader = new String[] {"time", "_col1", "_col2"};
     String[] retArray =
         new String[] {
-          "1,1,null,",
-          "2,2,null,",
-          "4,4,null,",
-          "5,5,null,",
-          "6,null,1.0,",
-          "5000000000,null,1.0,",
-          "5000000001,8,null,"
+          "1997-01-01T08:00:00.001Z,null,null,",
+          "1997-01-01T08:00:00.002Z,1.0,null,",
+          "1997-01-01T08:00:00.003Z,null,null,",
+          "1997-01-01T08:00:00.004Z,null,null,",
+          "1997-01-01T08:00:00.005Z,1.0,null,",
+          "1997-01-01T08:00:00.006Z,null,1.0,",
+          "1970-02-27T20:53:20.000Z,null,1.0,",
+          "1970-02-27T20:53:20.001Z,null,null,"
         };
     resultSetEqualTest(
-        "select change_points(s1), diff(s2, 'ignoreNull'='false') from 
root.db.d1",
+        "select time, Diff(s1, false), diff(s2, false) from table1 where 
device_id='d1'",
         expectedHeader,
         retArray);
 
     // align by device
-    expectedHeader =
-        new String[] {
-          TIMESTAMP_STR, DEVICE, "change_points(s1)", "diff(s2, 
\"ignoreNull\"=\"false\")"
-        };
+    expectedHeader = new String[] {"time", "device_id", "_col1", "_col2"};
     retArray =
         new String[] {
-          "1,root.db.d1,1,null,",
-          "2,root.db.d1,2,null,",
-          "4,root.db.d1,4,null,",
-          "5,root.db.d1,5,null,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000001,root.db.d1,8,null,",
-          "1,root.db.d2,1,null,",
-          "2,root.db.d2,2,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d2,4,null,",
+          "1997-01-01T08:00:00.001Z,d1,null,null,",
+          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
+          "1997-01-01T08:00:00.003Z,d1,null,null,",
+          "1997-01-01T08:00:00.004Z,d1,null,null,",
+          "1997-01-01T08:00:00.005Z,d1,1.0,null,",
+          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.001Z,d1,null,null,",
+          "1997-01-01T08:00:00.001Z,d2,null,null",
+          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
+          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
+          "1970-02-27T20:53:20.001Z,d2,null,null,",
         };
     resultSetEqualTest(
-        "select change_points(s1), diff(s2, 'ignoreNull'='false') from 
root.db.d1, root.db.d2 align by device",
+        "select time, device_id, Diff(s1, false), diff(s2, false) from table1 
where device_id='d1' or device_id='d2' order by device_id",
         expectedHeader,
         retArray);
 
     // align by device + order by time
-    expectedHeader =
-        new String[] {
-          TIMESTAMP_STR, DEVICE, "change_points(s1)", "diff(s2, 
\"ignoreNull\"=\"false\")"
-        };
     retArray =
         new String[] {
-          "1,root.db.d1,1,null,",
-          "1,root.db.d2,1,null,",
-          "2,root.db.d1,2,null,",
-          "2,root.db.d2,2,1.0,",
-          "4,root.db.d1,4,null,",
-          "5,root.db.d1,5,null,",
-          "6,root.db.d1,null,1.0,",
-          "5000000000,root.db.d1,null,1.0,",
-          "5000000000,root.db.d2,null,1.0,",
-          "5000000001,root.db.d1,8,null,",
-          "5000000001,root.db.d2,4,null,",
+          "1997-01-01T08:00:00.001Z,d1,null,null,",
+          "1997-01-01T08:00:00.001Z,d2,null,null",
+          "1997-01-01T08:00:00.002Z,d1,1.0,null,",
+          "1997-01-01T08:00:00.002Z,d2,1.0,1.0,",
+          "1997-01-01T08:00:00.003Z,d1,null,null,",
+          "1997-01-01T08:00:00.004Z,d1,null,null,",
+          "1997-01-01T08:00:00.005Z,d1,1.0,null,",
+          "1997-01-01T08:00:00.006Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.000Z,d1,null,1.0,",
+          "1970-02-27T20:53:20.000Z,d2,null,1.0,",
+          "1970-02-27T20:53:20.001Z,d1,null,null,",
+          "1970-02-27T20:53:20.001Z,d2,null,null,",
         };
     resultSetEqualTest(
-        "select change_points(s1), diff(s2, 'ignoreNull'='false') from 
root.db.d1, root.db.d2 order by time align by device",
+        "select time, device_id, Diff(s1, false), diff(s2, false) where 
device_id='d1' or device_id='d2' order by time,device_id",
         expectedHeader,
         retArray);
   }
 
   @Test
   public void testCaseInSensitive() {
-    String[] expectedHeader = new String[] {TIMESTAMP_STR, "root.db.d1.s1", 
"root.db.d1.s2"};
-    String[] retArray = new String[] {"2,2,null,", "4,4,null,", "5,5,5.0,"};
-    resultSetEqualTest(
-        "select s1, s2 from root.db.d1 where Diff(s1) between 1 and 2", 
expectedHeader, retArray);
-
-    retArray = new String[] {};
+    String[] expectedHeader = new String[] {"time", "s1", "s2"};
+    String[] retArray =
+        new String[] {
+          "1997-01-01T08:00:00.002Z,2,null,",
+          "1997-01-01T08:00:00.004Z,4,null,",
+          "1997-01-01T08:00:00.005Z,5,5.0,"
+        };
     resultSetEqualTest(
-        "select s1, s2 from root.db.d1 where Diff(notExist) between 1 and 2",
+        "select time, s1, s2 from table1 where device_id='d1' and diff(s1) 
between 1 and 2",
         expectedHeader,
         retArray);
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java
index 88f235902e0..421fc8eaebf 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.analyzer;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
 import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
@@ -57,6 +58,9 @@ public class Analyzer {
 
   public Analysis analyze(Statement statement) {
     Analysis analysis = new Analysis(statement, parameterLookup);
+    if (!session.getDatabaseName().isPresent()) {
+      throw new SemanticException("database is not specified");
+    }
     analysis.setDatabaseName(session.getDatabaseName().get());
     StatementAnalyzer analyzer =
         statementAnalyzerFactory.createStatementAnalyzer(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToFilterVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToFilterVisitor.java
index 3c520aae3f7..80fcf5bce87 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToFilterVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToFilterVisitor.java
@@ -36,6 +36,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNullPredicate;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LikePredicate;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NotExpression;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullIfExpression;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SearchedCaseExpression;
@@ -326,7 +327,13 @@ public class ConvertPredicateToFilterVisitor
   }
 
   public static double getDoubleValue(Expression expression) {
-    return ((DoubleLiteral) expression).getValue();
+    if (expression instanceof DoubleLiteral) {
+      return ((DoubleLiteral) expression).getValue();
+    } else if (expression instanceof LongLiteral) {
+      return ((LongLiteral) expression).getParsedValue();
+    } else {
+      throw new IllegalArgumentException("expression should be numeric, actual 
is " + expression);
+    }
   }
 
   public static boolean getBooleanValue(Expression expression) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
index 8653d92aff2..3823406d1c3 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
@@ -21,6 +21,7 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.planner.ir;
 
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression;
 
@@ -68,9 +69,8 @@ public final class NormalizeOrExpressionRewriter {
           .forEach(
               (expression, values) -> {
                 if (values.size() > 1) {
-                  // TODO mergeToInListExpression may have more than one value
                   inPredicateBuilder.add(
-                      new InPredicate(expression, 
mergeToInListExpression(values).get(0)));
+                      new InPredicate(expression, 
mergeToInListExpression(values)));
                   expressionToSkipBuilder.add(expression);
                 }
               });
@@ -99,21 +99,22 @@ public final class NormalizeOrExpressionRewriter {
               .build());
     }
 
-    private List<Expression> mergeToInListExpression(Collection<Expression> 
expressions) {
+    private InListExpression mergeToInListExpression(Collection<Expression> 
expressions) {
       LinkedHashSet<Expression> expressionValues = new LinkedHashSet<>();
       for (Expression expression : expressions) {
         if (expression instanceof ComparisonExpression
             && ((ComparisonExpression) expression).getOperator() == EQUAL) {
           expressionValues.add(((ComparisonExpression) expression).getRight());
-        } else if (expression instanceof InPredicate) {
-          // TODO inPredicate has getValues method
-          expressionValues.add(((InPredicate) expression).getValue());
+        } else if (expression instanceof InPredicate
+            && ((InPredicate) expression).getValueList() instanceof 
InListExpression) {
+          expressionValues.addAll(
+              ((InListExpression) ((InPredicate) 
expression).getValueList()).getValues());
         } else {
           throw new IllegalStateException("Unexpected expression: " + 
expression);
         }
       }
 
-      return ImmutableList.copyOf(expressionValues);
+      return new InListExpression(ImmutableList.copyOf(expressionValues));
     }
 
     private Map<Expression, Collection<Expression>> 
groupComparisonAndInPredicate(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index ae9b8bf1d7a..49834085b97 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -1385,6 +1385,14 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
     return new CurrentTime(getLocation(ctx), function);
   }
 
+  @Override
+  public Node 
visitDateTimeExpression(RelationalSqlParser.DateTimeExpressionContext ctx) {
+    return new LongLiteral(
+        getLocation(ctx),
+        String.valueOf(
+            parseDateExpression(ctx.dateExpression(), 
CommonDateTimeUtils.currentTime())));
+  }
+
   @Override
   public Node visitTrim(RelationalSqlParser.TrimContext ctx) {
     if (ctx.FROM() != null && ctx.trimsSpecification() == null && ctx.trimChar 
== null) {
@@ -1589,6 +1597,15 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
     return new BooleanLiteral(getLocation(ctx), ctx.getText());
   }
 
+  @Override
+  public Node visitDatetimeLiteral(RelationalSqlParser.DatetimeLiteralContext 
ctx) {
+    return new LongLiteral(
+        getLocation(ctx),
+        String.valueOf(
+            parseDateTimeFormat(
+                ctx.getChild(0).getText(), CommonDateTimeUtils.currentTime(), 
zoneId)));
+  }
+
   @Override
   public Node visitParameter(RelationalSqlParser.ParameterContext ctx) {
     Parameter parameter = new Parameter(getLocation(ctx), parameterPosition);
diff --git 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index 05d2a881735..a10ea67456a 100644
--- 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++ 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -442,10 +442,10 @@ timeValue
     ;
 
 dateExpression
-    : datetimeLiteral ((PLUS | MINUS) timeDuration)*
+    : datetime ((PLUS | MINUS) timeDuration)*
     ;
 
-datetimeLiteral
+datetime
     : DATETIME_VALUE
     | NOW '(' ')'
     ;
@@ -543,6 +543,7 @@ valueExpression
 
 primaryExpression
     : literalExpression                                                        
           #literal
+    | dateExpression                                                           
           #dateTimeExpression
     | '(' expression (',' expression)+ ')'                                     
           #rowConstructor
     | ROW '(' expression (',' expression)* ')'                                 
           #rowConstructor
     | qualifiedName '(' (label=identifier '.')? ASTERISK ')'                   
           #functionCall
@@ -570,6 +571,7 @@ literalExpression
     | number                                                                   
           #numericLiteral
     | booleanValue                                                             
           #booleanLiteral
     | string                                                                   
           #stringLiteral
+    | datetime                                                                 
           #datetimeLiteral
     | BINARY_LITERAL                                                           
           #binaryLiteral
     | QUESTION_MARK                                                            
           #parameter
     ;

Reply via email to