You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2022/07/04 07:08:50 UTC

[iotdb] branch master updated: [IOTDB-3572] Improve semantic checking of null value fill (#6562)

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

jackietien 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 f4bb4af023 [IOTDB-3572] Improve semantic checking of null value fill (#6562)
f4bb4af023 is described below

commit f4bb4af023e5c8ff9e5dd28d687bfb850fad288b
Author: liuminghui233 <36...@users.noreply.github.com>
AuthorDate: Mon Jul 4 15:08:45 2022 +0800

    [IOTDB-3572] Improve semantic checking of null value fill (#6562)
---
 .../db/it/aligned/IoTDBAlignedSeriesQueryIT.java   |   2 +-
 .../iotdb/db/it/query/IoTDBNullValueFillIT.java    | 394 +++++++++++++++++++++
 .../apache/iotdb/db/mpp/plan/analyze/Analyzer.java |  16 +-
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |  10 +
 .../mpp/plan/statement/literal/BooleanLiteral.java |   7 +-
 .../mpp/plan/statement/literal/DoubleLiteral.java  |   9 +-
 .../db/mpp/plan/statement/literal/Literal.java     |   2 +
 .../db/mpp/plan/statement/literal/LongLiteral.java |   8 +-
 .../db/mpp/plan/statement/literal/NullLiteral.java |   5 +
 .../mpp/plan/statement/literal/StringLiteral.java  |   5 +
 10 files changed, 452 insertions(+), 6 deletions(-)

diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/aligned/IoTDBAlignedSeriesQueryIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/aligned/IoTDBAlignedSeriesQueryIT.java
index 6050a012bc..fe12704faf 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/aligned/IoTDBAlignedSeriesQueryIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/aligned/IoTDBAlignedSeriesQueryIT.java
@@ -3265,7 +3265,7 @@ public class IoTDBAlignedSeriesQueryIT {
       try (ResultSet resultSet =
           statement.executeQuery(
               "select count(s1), sum(s2), avg(s1) from root.sg1.d1 "
-                  + "where time > 5 GROUP BY ([1, 41), 10ms) FILL (previous, 15ms) align by device")) {
+                  + "where time > 5 GROUP BY ([1, 41), 10ms) FILL (previous) align by device")) {
         cnt = 0;
         while (resultSet.next()) {
           String ans =
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBNullValueFillIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBNullValueFillIT.java
new file mode 100644
index 0000000000..59264a60ad
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBNullValueFillIT.java
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.it.query;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import static org.apache.iotdb.db.it.utils.TestUtils.assertTestFail;
+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.db.it.utils.TestUtils.resultSetEqualWithDescOrderTest;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({ClusterIT.class}) // TODO add LocalStandaloneIT
+public class IoTDBNullValueFillIT {
+
+  /**
+   * [root.sg1.d1 (aligned)]
+   *
+   * <p>Time, s1[INT32], s2[INT64], s3[FLOAT], s4[DOUBLE], s5[BOOLEAN], s6[TEXT]<br>
+   * 1, null, 1, null, 1.0, null, t1<br>
+   * 2, 2, 2, 2.0, 2.0, true, t2<br>
+   * 3, 3, null, 3.0, null, false, null<br>
+   * 4, null, 4, null, 4.0, null, t4<br>
+   * 5, 5, 5, 5.0, 5.0, false, t5<br>
+   * 6, null, 6, null, null, false, null<br>
+   * 7, null, null, null, null, null, null<br>
+   * 8, 8, 8, 8.0, 8.0, true, t8<br>
+   * 9, 9, null, 9.0, null, true, null
+   *
+   * <p>[root.sg1.d2 (non-aligned)]
+   *
+   * <p>Time, s1[INT32], s2[INT64], s3[FLOAT], s4[DOUBLE], s5[BOOLEAN], s6[TEXT]<br>
+   * 1, 1, null, 1.0, null, true, null<br>
+   * 2, 2, 2, 2.0, 2.0, true, t2<br>
+   * 3, null, 3, null, 3.0, null, t3<br>
+   * 4, 4, null, 4.0, null, false, null<br>
+   * 5, 5, 5, 5.0, 5.0, false, t5<br>
+   * 6, 6, null, 6.0, null, false, null<br>
+   * 7, null, null, null, null, null, null<br>
+   * 8, 8, 8, 8.0, 8.0, true, t8<br>
+   * 9, null, 9, null, 9.0, null, t9
+   */
+  private static final String[] sqls =
+      new String[] {
+        "SET STORAGE GROUP TO root.sg1",
+        "create aligned timeseries root.sg1.d1(s1 INT32, s2 INT64, s3 FLOAT, s4 DOUBLE, s5 BOOLEAN, s6 TEXT)",
+        "insert into root.sg1.d1(time, s2, s4, s6) aligned values(1, 1, 1.0, 't1')",
+        "insert into root.sg1.d1(time, s1, s2, s3, s4, s5, s6) aligned values(2, 2, 2, 2.0, 2.0, true, 't2')",
+        "insert into root.sg1.d1(time, s1, s3, s5) aligned values(3, 3, 3.0, false)",
+        "insert into root.sg1.d1(time, s2, s4, s6) aligned values(4, 4, 4.0, 't4')",
+        "insert into root.sg1.d1(time, s1, s2, s3, s4, s5, s6) aligned values(5, 5, 5, 5.0, 5.0, false, 't5')",
+        "insert into root.sg1.d1(time, s2, s4, s6) aligned values(6, 6, 6.0, 't6')",
+        "insert into root.sg1.d1(time, s1, s2, s3, s4, s5, s6) aligned values(8, 8, 8, 8.0, 8.0, true, 't8')",
+        "insert into root.sg1.d1(time, s1, s3, s5) aligned values(9, 9, 9.0, true)",
+        "create timeseries root.sg1.d2.s1 INT32",
+        "create timeseries root.sg1.d2.s2 INT64",
+        "create timeseries root.sg1.d2.s3 FLOAT",
+        "create timeseries root.sg1.d2.s4 DOUBLE",
+        "create timeseries root.sg1.d2.s5 BOOLEAN",
+        "create timeseries root.sg1.d2.s6 TEXT",
+        "insert into root.sg1.d2(time, s1, s3, s5) values(1, 1, 1.0, true)",
+        "insert into root.sg1.d2(time, s1, s2, s3, s4, s5, s6) values(2, 2, 2, 2.0, 2.0, true, 't2')",
+        "insert into root.sg1.d2(time, s2, s4, s6) values(3, 3, 3.0, 't3')",
+        "insert into root.sg1.d2(time, s1, s3, s5) values(4, 4, 4.0, false)",
+        "insert into root.sg1.d2(time, s1, s2, s3, s4, s5, s6) values(5, 5, 5, 5.0, 5.0, false, 't5')",
+        "insert into root.sg1.d2(time, s1, s3, s5) values(6, 6, 6.0, false)",
+        "insert into root.sg1.d2(time, s1, s2, s3, s4, s5, s6) values(8, 8, 8, 8.0, 8.0, true, 't8')",
+        "insert into root.sg1.d2(time, s2, s4, s6) values(9, 9, 9.0, 't9')"
+      };
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    EnvFactory.getEnv().initBeforeClass();
+    prepareData(sqls);
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanAfterClass();
+  }
+
+  @Test
+  public void previousFillTest() {
+    String[] expectedHeader =
+        new String[] {
+          "Time",
+          "root.sg1.d1.s1",
+          "root.sg1.d1.s2",
+          "root.sg1.d1.s3",
+          "root.sg1.d1.s4",
+          "root.sg1.d1.s5",
+          "root.sg1.d1.s6"
+        };
+    String[] retArray =
+        new String[] {
+          "1,null,1,null,1.0,null,t1,",
+          "2,2,2,2.0,2.0,true,t2,",
+          "3,3,2,3.0,2.0,false,t2,",
+          "4,3,4,3.0,4.0,false,t4,",
+          "5,5,5,5.0,5.0,false,t5,",
+          "6,5,6,5.0,6.0,false,t6,",
+          "8,8,8,8.0,8.0,true,t8,",
+          "9,9,8,9.0,8.0,true,t8,"
+        };
+    resultSetEqualTest(
+        "select s1, s2, s3, s4, s5, s6 from root.sg1.d1 fill(previous)", expectedHeader, retArray);
+  }
+
+  @Test
+  public void previousDescFillTest() {
+    String[] expectedHeader =
+        new String[] {
+          "Time",
+          "root.sg1.d1.s1",
+          "root.sg1.d1.s2",
+          "root.sg1.d1.s3",
+          "root.sg1.d1.s4",
+          "root.sg1.d1.s5",
+          "root.sg1.d1.s6"
+        };
+    String[] retArray =
+        new String[] {
+          "9,9,null,9.0,null,true,null,",
+          "8,8,8,8.0,8.0,true,t8,",
+          "6,8,6,8.0,6.0,true,t6,",
+          "5,5,5,5.0,5.0,false,t5,",
+          "4,5,4,5.0,4.0,false,t4,",
+          "3,3,4,3.0,4.0,false,t4,",
+          "2,2,2,2.0,2.0,true,t2,",
+          "1,2,1,2.0,1.0,true,t1,"
+        };
+    resultSetEqualTest(
+        "select s1, s2, s3, s4, s5, s6 from root.sg1.d1 fill(previous) order by time desc",
+        expectedHeader,
+        retArray);
+  }
+
+  @Test
+  public void previousFillAlignByDeviceTest() {
+    String[] expectedHeader = new String[] {"Time", "Device", "s1", "s2", "s3", "s4", "s5", "s6"};
+    String[] retArray =
+        new String[] {
+          "1,root.sg1.d1,null,1,null,1.0,null,t1,",
+          "2,root.sg1.d1,2,2,2.0,2.0,true,t2,",
+          "3,root.sg1.d1,3,2,3.0,2.0,false,t2,",
+          "4,root.sg1.d1,3,4,3.0,4.0,false,t4,",
+          "5,root.sg1.d1,5,5,5.0,5.0,false,t5,",
+          "6,root.sg1.d1,5,6,5.0,6.0,false,t6,",
+          "8,root.sg1.d1,8,8,8.0,8.0,true,t8,",
+          "9,root.sg1.d1,9,8,9.0,8.0,true,t8,",
+          "1,root.sg1.d2,1,8,1.0,8.0,true,t8,",
+          "2,root.sg1.d2,2,2,2.0,2.0,true,t2,",
+          "3,root.sg1.d2,2,3,2.0,3.0,true,t3,",
+          "4,root.sg1.d2,4,3,4.0,3.0,false,t3,",
+          "5,root.sg1.d2,5,5,5.0,5.0,false,t5,",
+          "6,root.sg1.d2,6,5,6.0,5.0,false,t5,",
+          "8,root.sg1.d2,8,8,8.0,8.0,true,t8,",
+          "9,root.sg1.d2,8,9,8.0,9.0,true,t9,"
+        };
+    resultSetEqualTest(
+        "select s1, s2, s3, s4, s5, s6 from root.sg1.* fill(previous) align by device",
+        expectedHeader,
+        retArray);
+  }
+
+  @Test
+  public void previousDescFillAlignByDeviceTest() {
+    String[] expectedHeader = new String[] {"Time", "Device", "s1", "s2", "s3", "s4", "s5", "s6"};
+    String[] retArray =
+        new String[] {
+          "9,root.sg1.d1,9,null,9.0,null,true,null,",
+          "8,root.sg1.d1,8,8,8.0,8.0,true,t8,",
+          "6,root.sg1.d1,8,6,8.0,6.0,true,t6,",
+          "5,root.sg1.d1,5,5,5.0,5.0,false,t5,",
+          "4,root.sg1.d1,5,4,5.0,4.0,false,t4,",
+          "3,root.sg1.d1,3,4,3.0,4.0,false,t4,",
+          "2,root.sg1.d1,2,2,2.0,2.0,true,t2,",
+          "1,root.sg1.d1,2,1,2.0,1.0,true,t1,",
+          "9,root.sg1.d2,2,9,2.0,9.0,true,t9,",
+          "8,root.sg1.d2,8,8,8.0,8.0,true,t8,",
+          "6,root.sg1.d2,6,8,6.0,8.0,false,t8,",
+          "5,root.sg1.d2,5,5,5.0,5.0,false,t5,",
+          "4,root.sg1.d2,4,5,4.0,5.0,false,t5,",
+          "3,root.sg1.d2,4,3,4.0,3.0,false,t3,",
+          "2,root.sg1.d2,2,2,2.0,2.0,true,t2,",
+          "1,root.sg1.d2,1,2,1.0,2.0,true,t2,"
+        };
+    resultSetEqualTest(
+        "select s1, s2, s3, s4, s5, s6 from root.sg1.* fill(previous) order by time desc align by device",
+        expectedHeader,
+        retArray);
+  }
+
+  @Test
+  @Ignore // TODO fix IOTDB-3724
+  public void linearFillTest() {
+    String[] expectedHeader =
+        new String[] {
+          "Time", "root.sg1.d1.s1", "root.sg1.d1.s2", "root.sg1.d1.s3", "root.sg1.d1.s4"
+        };
+    String[] retArray =
+        new String[] {
+          "1,null,1,null,1.0,",
+          "2,2,2,2.0,2.0,",
+          "3,3,3,3.0,3.0,",
+          "4,4,4,4.0,4.0,",
+          "5,5,5,5.0,5.0,",
+          "6,6,6,6.5,6.0,",
+          "8,8,8,8.0,8.0,",
+          "9,9,null,9.0,null,"
+        };
+    resultSetEqualWithDescOrderTest(
+        "select s1, s2, s3, s4 from root.sg1.d1 fill(linear)", expectedHeader, retArray);
+  }
+
+  @Test
+  public void linearFillAlignByDeviceTest() {
+    assertTestFail(
+        "select s1, s2, s3, s4 from root.sg1.d1 fill(linear) align by device",
+        "Linear fill is not supported in align by device query yet.");
+  }
+
+  @Test
+  public void linearFillDataTypeMisMatchTest() {
+    assertTestFail(
+        "select s1, s5 from root.sg1.d1 fill(linear)",
+        "Data type mismatch: column 'root.sg1.d1.s5' (dataType 'BOOLEAN') doesn't support linear fill.");
+    assertTestFail(
+        "select s1, s6 from root.sg1.d1 fill(linear)",
+        "Data type mismatch: column 'root.sg1.d1.s6' (dataType 'TEXT') doesn't support linear fill.");
+  }
+
+  @Test
+  public void intFillTest() {
+    String[] expectedHeader =
+        new String[] {
+          "Time",
+          "root.sg1.d1.s1",
+          "root.sg1.d1.s2",
+          "root.sg1.d1.s3",
+          "root.sg1.d1.s4",
+          "root.sg1.d1.s6"
+        };
+    String[] retArray =
+        new String[] {
+          "1,1000,1,1000.0,1.0,t1,",
+          "2,2,2,2.0,2.0,t2,",
+          "3,3,1000,3.0,1000.0,1000,",
+          "4,1000,4,1000.0,4.0,t4,",
+          "5,5,5,5.0,5.0,t5,",
+          "6,1000,6,1000.0,6.0,t6,",
+          "8,8,8,8.0,8.0,t8,",
+          "9,9,1000,9.0,1000.0,1000,"
+        };
+    resultSetEqualWithDescOrderTest(
+        "select s1, s2, s3, s4, s6 from root.sg1.d1 fill(1000)", expectedHeader, retArray);
+  }
+
+  @Test
+  public void intFillDataTypeMisMatchTest() {
+    assertTestFail(
+        "select s1, s5 from root.sg1.d1 fill(1000)",
+        "Data type mismatch: column 'root.sg1.d1.s5' (dataType 'BOOLEAN') doesn't support fill with '1000' (dataType 'INT64').");
+  }
+
+  @Test
+  public void floatFillTest() {
+    String[] expectedHeader =
+        new String[] {"Time", "root.sg1.d1.s3", "root.sg1.d1.s4", "root.sg1.d1.s6"};
+    String[] retArray =
+        new String[] {
+          "1,3.14,1.0,t1,",
+          "2,2.0,2.0,t2,",
+          "3,3.0,3.14,3.14,",
+          "4,3.14,4.0,t4,",
+          "5,5.0,5.0,t5,",
+          "6,3.14,6.0,t6,",
+          "8,8.0,8.0,t8,",
+          "9,9.0,3.14,3.14,"
+        };
+    resultSetEqualWithDescOrderTest(
+        "select s3, s4, s6 from root.sg1.d1 fill(3.14)", expectedHeader, retArray);
+  }
+
+  @Test
+  public void floatFillDataTypeMisMatchTest() {
+    assertTestFail(
+        "select s1, s3 from root.sg1.d1 fill(3.14)",
+        "Data type mismatch: column 'root.sg1.d1.s1' (dataType 'INT32') doesn't support fill with '3.14' (dataType 'DOUBLE').");
+    assertTestFail(
+        "select s2, s3 from root.sg1.d1 fill(3.14)",
+        "Data type mismatch: column 'root.sg1.d1.s2' (dataType 'INT64') doesn't support fill with '3.14' (dataType 'DOUBLE').");
+    assertTestFail(
+        "select s5, s3 from root.sg1.d1 fill(3.14)",
+        "Data type mismatch: column 'root.sg1.d1.s5' (dataType 'BOOLEAN') doesn't support fill with '3.14' (dataType 'DOUBLE').");
+  }
+
+  @Test
+  public void booleanFillTest() {
+    String[] expectedHeader = new String[] {"Time", "root.sg1.d1.s5", "root.sg1.d1.s6"};
+    String[] retArray =
+        new String[] {
+          "1,true,t1,",
+          "2,true,t2,",
+          "3,false,true,",
+          "4,true,t4,",
+          "5,false,t5,",
+          "6,true,t6,",
+          "8,true,t8,",
+          "9,true,true,"
+        };
+    resultSetEqualWithDescOrderTest(
+        "select s5, s6 from root.sg1.d1 fill(true)", expectedHeader, retArray);
+  }
+
+  @Test
+  public void booleanFillDataTypeMisMatchTest() {
+    assertTestFail(
+        "select s5, s1 from root.sg1.d1 fill(true)",
+        "Data type mismatch: column 'root.sg1.d1.s1' (dataType 'INT32') doesn't support fill with 'true' (dataType 'BOOLEAN').");
+    assertTestFail(
+        "select s5, s2 from root.sg1.d1 fill(true)",
+        "Data type mismatch: column 'root.sg1.d1.s2' (dataType 'INT64') doesn't support fill with 'true' (dataType 'BOOLEAN').");
+    assertTestFail(
+        "select s5, s3 from root.sg1.d1 fill(true)",
+        "Data type mismatch: column 'root.sg1.d1.s3' (dataType 'FLOAT') doesn't support fill with 'true' (dataType 'BOOLEAN').");
+    assertTestFail(
+        "select s5, s4 from root.sg1.d1 fill(true)",
+        "Data type mismatch: column 'root.sg1.d1.s4' (dataType 'DOUBLE') doesn't support fill with 'true' (dataType 'BOOLEAN').");
+  }
+
+  @Test
+  public void textFillTest() {
+    String[] expectedHeader = new String[] {"Time", "root.sg1.d1.s6", "root.sg1.d2.s6"};
+    String[] retArray =
+        new String[] {
+          "1,t1,t0,",
+          "2,t2,t2,",
+          "3,t0,t3,",
+          "4,t4,t0,",
+          "5,t5,t5,",
+          "6,t6,t0,",
+          "8,t8,t8,",
+          "9,t0,t9,"
+        };
+    resultSetEqualWithDescOrderTest(
+        "select s6 from root.sg1.d1, root.sg1.d2 fill('t0')", expectedHeader, retArray);
+  }
+
+  @Test
+  public void textFillDataTypeMisMatchTest() {
+    assertTestFail(
+        "select s6, s1 from root.sg1.d1 fill('t0')",
+        "Data type mismatch: column 'root.sg1.d1.s1' (dataType 'INT32') doesn't support fill with 't0' (dataType 'TEXT').");
+    assertTestFail(
+        "select s6, s2 from root.sg1.d1 fill('t0')",
+        "Data type mismatch: column 'root.sg1.d1.s2' (dataType 'INT64') doesn't support fill with 't0' (dataType 'TEXT').");
+    assertTestFail(
+        "select s6, s3 from root.sg1.d1 fill('t0')",
+        "Data type mismatch: column 'root.sg1.d1.s3' (dataType 'FLOAT') doesn't support fill with 't0' (dataType 'TEXT').");
+    assertTestFail(
+        "select s6, s4 from root.sg1.d1 fill('t0')",
+        "Data type mismatch: column 'root.sg1.d1.s4' (dataType 'DOUBLE') doesn't support fill with 't0' (dataType 'TEXT').");
+    assertTestFail(
+        "select s6, s5 from root.sg1.d1 fill('t0')",
+        "Data type mismatch: column 'root.sg1.d1.s5' (dataType 'BOOLEAN') doesn't support fill with 't0' (dataType 'TEXT').");
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
index f3c89dd095..2dd7c55ff9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
@@ -416,16 +416,28 @@ public class Analyzer {
               TSDataType checkedDataType = typeProvider.getType(fillColumn.getExpressionString());
               if (!fillComponent.getFillValue().isDataTypeConsistency(checkedDataType)) {
                 throw new SemanticException(
-                    "FILL: the data type of the fill value should be the same as the output column");
+                    String.format(
+                        "Data type mismatch: column '%s' (dataType '%s') doesn't support fill with '%s' (dataType '%s').",
+                        fillColumn.getExpressionString(),
+                        checkedDataType,
+                        fillComponent.getFillValue().getBinary(),
+                        fillComponent.getFillValue().getDataTypeString()));
               }
             }
           } else if (fillComponent.getFillPolicy() == FillPolicy.LINEAR) {
+            // TODO support linear fill in align by device query
+            if (queryStatement.isAlignByDevice()) {
+              throw new SemanticException(
+                  "Linear fill is not supported in align by device query yet.");
+            }
+
             for (Expression fillColumn : fillColumnList) {
               TSDataType checkedDataType = typeProvider.getType(fillColumn.getExpressionString());
               if (!checkedDataType.isNumeric()) {
                 throw new SemanticException(
                     String.format(
-                        "FILL: dataType %s doesn't support linear fill.", checkedDataType));
+                        "Data type mismatch: column '%s' (dataType '%s') doesn't support linear fill.",
+                        fillColumn.getExpressionString(), checkedDataType));
               }
             }
           }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index affb77b9ae..00079c29b3 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -976,8 +976,14 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
   public void parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
     FillComponent fillComponent = new FillComponent();
     if (ctx.linearClause() != null) {
+      if (ctx.linearClause().DURATION_LITERAL().size() > 0) {
+        throw new SemanticException("The specified fill time range is not supported.");
+      }
       fillComponent.setFillPolicy(FillPolicy.LINEAR);
     } else if (ctx.previousClause() != null) {
+      if (ctx.previousClause().DURATION_LITERAL() != null) {
+        throw new SemanticException("The specified fill time range is not supported.");
+      }
       fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
     } else if (ctx.specificValueClause() != null) {
       fillComponent.setFillPolicy(FillPolicy.VALUE);
@@ -987,6 +993,10 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
       } else {
         throw new SemanticException("fill value cannot be null");
       }
+    } else if (ctx.previousUntilLastClause() != null) {
+      throw new SemanticException("PREVIOUSUNTILLAST fill is not supported yet.");
+    } else if (ctx.oldTypeClause() != null) {
+      throw new SemanticException("The specified fill datatype is not supported.");
     }
     queryStatement.setFillComponent(fillComponent);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/BooleanLiteral.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/BooleanLiteral.java
index 132024e9a0..8cbe5db20f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/BooleanLiteral.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/BooleanLiteral.java
@@ -54,7 +54,12 @@ public class BooleanLiteral extends Literal {
 
   @Override
   public boolean isDataTypeConsistency(TSDataType dataType) {
-    return dataType == TSDataType.BOOLEAN;
+    return dataType == TSDataType.BOOLEAN || dataType == TSDataType.TEXT;
+  }
+
+  @Override
+  public String getDataTypeString() {
+    return TSDataType.BOOLEAN.toString();
   }
 
   @Override
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/DoubleLiteral.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/DoubleLiteral.java
index 508ba4f514..868d87276a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/DoubleLiteral.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/DoubleLiteral.java
@@ -53,7 +53,14 @@ public class DoubleLiteral extends Literal {
 
   @Override
   public boolean isDataTypeConsistency(TSDataType dataType) {
-    return dataType == TSDataType.FLOAT || dataType == TSDataType.DOUBLE;
+    return dataType == TSDataType.FLOAT
+        || dataType == TSDataType.DOUBLE
+        || dataType == TSDataType.TEXT;
+  }
+
+  @Override
+  public String getDataTypeString() {
+    return TSDataType.DOUBLE.toString();
   }
 
   @Override
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/Literal.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/Literal.java
index ec9c348f4c..710d9b9694 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/Literal.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/Literal.java
@@ -62,6 +62,8 @@ public abstract class Literal extends StatementNode {
 
   public abstract boolean isDataTypeConsistency(TSDataType dataType);
 
+  public abstract String getDataTypeString();
+
   public boolean getBoolean() {
     throw new UnsupportedOperationException(getClass().getName());
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/LongLiteral.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/LongLiteral.java
index dd9e3c507f..6014f1c387 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/LongLiteral.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/LongLiteral.java
@@ -60,7 +60,13 @@ public class LongLiteral extends Literal {
     return dataType == TSDataType.INT32
         || dataType == TSDataType.INT64
         || dataType == TSDataType.FLOAT
-        || dataType == TSDataType.DOUBLE;
+        || dataType == TSDataType.DOUBLE
+        || dataType == TSDataType.TEXT;
+  }
+
+  @Override
+  public String getDataTypeString() {
+    return TSDataType.INT64.toString();
   }
 
   @Override
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/NullLiteral.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/NullLiteral.java
index 67d0cfe818..51221a494a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/NullLiteral.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/NullLiteral.java
@@ -44,6 +44,11 @@ public class NullLiteral extends Literal {
     return false;
   }
 
+  @Override
+  public String getDataTypeString() {
+    return "NULL";
+  }
+
   @Override
   public Binary getBinary() {
     return new Binary("null");
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/StringLiteral.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/StringLiteral.java
index 6bfb05e561..118680ce47 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/StringLiteral.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/literal/StringLiteral.java
@@ -56,6 +56,11 @@ public class StringLiteral extends Literal {
     return dataType == TSDataType.TEXT;
   }
 
+  @Override
+  public String getDataTypeString() {
+    return TSDataType.TEXT.toString();
+  }
+
   @Override
   public Binary getBinary() {
     return new Binary(value);