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);