This is an automated email from the ASF dual-hosted git repository.
caogaofei pushed a commit to branch beyyes/improve_query_fe
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/beyyes/improve_query_fe by
this push:
new 796e3df9783 add ut for QueryStatement and StatementGenerator
796e3df9783 is described below
commit 796e3df9783fafd2d01389a30758fbd0631cc487
Author: Beyyes <[email protected]>
AuthorDate: Mon Jun 26 20:03:22 2023 +0800
add ut for QueryStatement and StatementGenerator
---
.../plan/scheduler/load/LoadTsFileScheduler.java | 11 +-
.../db/mpp/plan/statement/crud/QueryStatement.java | 25 +---
.../db/mpp/plan/parser/StatementGeneratorTest.java | 38 ++++--
.../db/mpp/plan/statement/QueryStatementTest.java | 147 +++++++++++++++++++++
4 files changed, 183 insertions(+), 38 deletions(-)
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/scheduler/load/LoadTsFileScheduler.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/scheduler/load/LoadTsFileScheduler.java
index f371e5e293e..6541ae4e5ef 100644
---
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/scheduler/load/LoadTsFileScheduler.java
+++
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/scheduler/load/LoadTsFileScheduler.java
@@ -327,12 +327,11 @@ public class LoadTsFileScheduler implements IScheduler {
dispatcher.dispatchLocally(instance);
} catch (FragmentInstanceDispatchException e) {
logger.warn(
- String.format(
- "Dispatch tsFile %s error to local error. Result status code %s.
"
- + "Result status message %s.",
- node.getTsFileResource().getTsFile(),
- TSStatusCode.representOf(e.getFailureStatus().getCode()).name(),
- e.getFailureStatus().getMessage()));
+ "Dispatch tsFile {} error to local error. Result status code {}. "
+ + "Result status message {}.",
+ node.getTsFileResource().getTsFile(),
+ TSStatusCode.representOf(e.getFailureStatus().getCode()).name(),
+ e.getFailureStatus().getMessage());
stateMachine.transitionToFailed(e.getFailureStatus());
return false;
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
index 2cf6154a1c4..d405696f0e2 100644
---
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
+++
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
@@ -333,10 +333,6 @@ public class QueryStatement extends Statement {
return resultSetFormat == ResultSetFormat.ALIGN_BY_DEVICE;
}
- public boolean disableAlign() {
- return resultSetFormat == ResultSetFormat.DISABLE_ALIGN;
- }
-
public boolean isOrderByTime() {
return orderByComponent != null && orderByComponent.isOrderByTime();
}
@@ -469,14 +465,11 @@ public class QueryStatement extends Statement {
return useWildcard;
}
- private static final String RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG =
+ public static final String RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG =
"Raw data and aggregation hybrid query is not supported.";
public void semanticCheck() {
if (isAggregationQuery()) {
- if (disableAlign()) {
- throw new SemanticException("AGGREGATION doesn't support disable align
clause.");
- }
if (groupByComponent != null && isGroupByLevel()) {
throw new SemanticException("GROUP BY CLAUSES doesn't support GROUP BY
LEVEL now.");
}
@@ -539,7 +532,7 @@ public class QueryStatement extends Statement {
Expression whereExpression = getWhereCondition().getPredicate();
if (ExpressionAnalyzer.identifyOutputColumnType(whereExpression, true)
== ResultColumn.ColumnType.AGGREGATION) {
- throw new SemanticException("aggregate functions are not supported in
WHERE clause");
+ throw new SemanticException("Aggregate functions are not supported in
WHERE clause");
}
}
@@ -600,9 +593,6 @@ public class QueryStatement extends Statement {
if (isAlignByDevice()) {
throw new SemanticException("Last query doesn't support align by
device.");
}
- if (disableAlign()) {
- throw new SemanticException("Disable align cannot be applied to LAST
query.");
- }
for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
Expression expression = resultColumn.getExpression();
if (!(expression instanceof TimeSeriesOperand)) {
@@ -630,19 +620,16 @@ public class QueryStatement extends Statement {
if (isSelectInto()) {
if (getSeriesLimit() > 0) {
- throw new SemanticException("select into: slimit clauses are not
supported.");
+ throw new SemanticException("Select into: slimit clauses are not
supported.");
}
if (getSeriesOffset() > 0) {
- throw new SemanticException("select into: soffset clauses are not
supported.");
- }
- if (disableAlign()) {
- throw new SemanticException("select into: disable align clauses are
not supported.");
+ throw new SemanticException("Select into: soffset clauses are not
supported.");
}
if (isLastQuery()) {
- throw new SemanticException("select into: last clauses are not
supported.");
+ throw new SemanticException("Select into: last clauses are not
supported.");
}
if (isGroupByTag()) {
- throw new SemanticException("select into: GROUP BY TAGS clause are not
supported.");
+ throw new SemanticException("Select into: GROUP BY TAGS clause are not
supported.");
}
}
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/parser/StatementGeneratorTest.java
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/parser/StatementGeneratorTest.java
index 1113033cfcd..f0747294d32 100644
---
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/parser/StatementGeneratorTest.java
+++
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/parser/StatementGeneratorTest.java
@@ -32,28 +32,35 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import static org.junit.Assert.assertEquals;
+
public class StatementGeneratorTest {
@Test
- public void testRawDataQuery() {
- List<String> selectExprList = Arrays.asList("s1", "s2");
- List<String> prefixPaths = Collections.singletonList("root.sg1.d1");
+ public void rawDataQueryTest() {
+ String sql = "SELECT s1, s2 FROM root.sg1.d1 WHERE time > 1 and s3 > 2
LIMIT 10 OFFSET 11";
checkQueryStatement(
- "SELECT s1, s2 FROM root.sg1.d1 LIMIT 10 OFFSET 10", selectExprList,
prefixPaths, 10, 10);
+ sql,
+ Arrays.asList("s1", "s2"),
+ Collections.singletonList("root.sg1.d1"),
+ "Time > 1 & s3 > 2",
+ 10,
+ 11);
}
@Test
- public void testGroupByTagWithDuplicatedKeys() {
+ public void groupByTagWithDuplicatedKeysTest() {
try {
checkQueryStatement(
"SELECT avg(*) FROM root.sg.** GROUP BY TAGS(k1, k2, k1)",
Collections.emptyList(),
Collections.emptyList(),
+ "",
10,
10);
Assert.fail();
} catch (SemanticException e) {
- Assert.assertEquals("duplicated key in GROUP BY TAGS: k1",
e.getMessage());
+ assertEquals("duplicated key in GROUP BY TAGS: k1", e.getMessage());
}
}
@@ -62,7 +69,8 @@ public class StatementGeneratorTest {
private void checkQueryStatement(
String sql,
List<String> selectExprList,
- List<String> prefixPaths,
+ List<String> fromPrefixPaths,
+ String wherePredicateString,
int rowLimit,
int rowOffset) {
QueryStatement statement =
@@ -72,20 +80,24 @@ public class StatementGeneratorTest {
int cnt = 0;
for (ResultColumn resultColumn :
statement.getSelectComponent().getResultColumns()) {
String selectExpr = resultColumn.getExpression().toString();
- Assert.assertEquals(selectExprList.get(cnt++), selectExpr);
+ assertEquals(selectExprList.get(cnt++), selectExpr);
}
- Assert.assertEquals(selectExprList.size(), cnt);
+ assertEquals(selectExprList.size(),
statement.getSelectComponent().getResultColumns().size());
// check FROM clause
cnt = 0;
for (PartialPath path : statement.getFromComponent().getPrefixPaths()) {
- Assert.assertEquals(prefixPaths.get(cnt++), path.toString());
+ assertEquals(fromPrefixPaths.get(cnt++), path.toString());
}
- Assert.assertEquals(prefixPaths.size(), cnt);
+ assertEquals(fromPrefixPaths.size(),
statement.getFromComponent().getPrefixPaths().size());
+
+ // check WHERE clause
+ assertEquals(
+ wherePredicateString,
statement.getWhereCondition().getPredicate().getExpressionString());
// check LIMIT & OFFSET clause
- Assert.assertEquals(rowLimit, statement.getRowLimit());
- Assert.assertEquals(rowOffset, statement.getRowOffset());
+ assertEquals(rowLimit, statement.getRowLimit());
+ assertEquals(rowOffset, statement.getRowOffset());
// TODO: add more clause
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/statement/QueryStatementTest.java
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/statement/QueryStatementTest.java
new file mode 100644
index 00000000000..e90ac2ad25d
--- /dev/null
+++
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/statement/QueryStatementTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.mpp.plan.statement;
+
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.parser.StatementGenerator;
+import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
+import org.apache.iotdb.tsfile.utils.Pair;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.List;
+
+import static
org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement.RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class QueryStatementTest {
+
+ private static final Logger logger =
LoggerFactory.getLogger(QueryStatementTest.class);
+
+ private static final String ALIGN_BY_DEVICE_ONE_LEVEL_ERROR =
+ "ALIGN BY DEVICE: the suffix paths can only be measurement or one-level
wildcard";
+
+ @Test
+ public void semanticCheckTest() {
+ List<Pair<String, String>> errorSqlWithMessages =
+ Arrays.asList(
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 GROUP BY ([2017-11-01T00:00:00,
2017-11-07T23:00:00),1d)",
+ "Common queries and aggregated queries are not allowed to
appear at the same time"),
+ new Pair<>(
+ "SELECT count(s1),s2 FROM root.sg.d1",
RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG),
+
+ // test for where clause
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 WHERE count(s1) > 0",
+ "Aggregate functions are not supported in WHERE clause"),
+
+ // test for having clause
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 HAVING(s1 > 0)",
+ "Expression of HAVING clause must to be an Aggregation"),
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 HAVING(count(s1) > 0)",
+ "Expression of HAVING clause can not be used in
NonAggregationQuery"),
+ new Pair<>(
+ "SELECT count(d1.s1) FROM root.sg.d1 GROUP BY level=1 HAVING
(count(s1) > 0)",
+ "When Having used with GroupByLevel: the suffix paths can only
be measurement or one-level wildcard"),
+ new Pair<>(
+ "SELECT count(s1) FROM root.sg.d1 GROUP BY level=1 HAVING
(count(sg.d1.s1) > 0)",
+ "When Having used with GroupByLevel: the suffix paths can only
be measurement or one-level wildcard"),
+
+ // test for align by device clause
+ new Pair<>(
+ "SELECT d1.s1 FROM root.sg.d1 align by device",
ALIGN_BY_DEVICE_ONE_LEVEL_ERROR),
+ new Pair<>(
+ "SELECT count(s1) FROM root.sg.d1 group by variation(sg.s1)
align by device",
+ ALIGN_BY_DEVICE_ONE_LEVEL_ERROR),
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 order by root.sg.d1.s1 align by
device",
+ ALIGN_BY_DEVICE_ONE_LEVEL_ERROR),
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 where root.sg.d1.s1 > 0 align by
device",
+ ALIGN_BY_DEVICE_ONE_LEVEL_ERROR),
+ new Pair<>(
+ "SELECT count(s1) FROM root.sg.d1 having(count(root.sg.d1.s1)
> 0) align by device",
+ ALIGN_BY_DEVICE_ONE_LEVEL_ERROR),
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 order by timeseries align by
device",
+ "Sorting by timeseries is only supported in last queries."),
+
+ // test for last query
+ new Pair<>(
+ "SELECT last s1 FROM root.sg.d1 align by device",
+ "Last query doesn't support align by device."),
+ new Pair<>(
+ "SELECT last s1+s2 FROM root.sg.d1",
+ "Last queries can only be applied on raw time series."),
+ new Pair<>(
+ "SELECT last s1 FROM root.sg.d1 order by device",
+ "Sorting by device is only supported in ALIGN BY DEVICE
queries."),
+ new Pair<>(
+ "SELECT last s1 FROM root.sg.d1 SLIMIT 1 SOFFSET 2",
+ "SLIMIT and SOFFSET can not be used in LastQuery."),
+
+ // test for select into clause
+ new Pair<>(
+ "SELECT s1 INTO root.sg.d2(t1) FROM root.sg.d1 SLIMIT 5",
+ "Select into: slimit clauses are not supported."),
+ new Pair<>(
+ "SELECT s1 INTO root.sg.d2(t1) FROM root.sg.d1 SOFFSET 6",
+ "Select into: soffset clauses are not supported."),
+ new Pair<>(
+ "SELECT last s1 INTO root.sg.d2(t1) FROM root.sg.d1",
+ "Select into: last clauses are not supported."),
+ new Pair<>(
+ "SELECT count(s1) INTO root.sg.d2(t1) FROM root.sg.d1 GROUP BY
TAGS(a)",
+ "Select into: GROUP BY TAGS clause are not supported."),
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 order by timeseries",
+ "Sorting by timeseries is only supported in last queries."),
+ new Pair<>(
+ "SELECT s1 FROM root.sg.d1 order by device",
+ "Sorting by device is only supported in ALIGN BY DEVICE
queries."));
+
+ for (Pair<String, String> pair : errorSqlWithMessages) {
+ String errorSql = pair.left;
+ String errorMsg = pair.right;
+ try {
+ checkErrorQuerySql(errorSql);
+ } catch (SemanticException e) {
+ assertEquals(errorMsg, e.getMessage());
+ } catch (Exception ex) {
+ logger.error("Meets error in test sql: {}", errorSql, ex);
+ fail();
+ }
+ }
+ }
+
+ private void checkErrorQuerySql(String sql) {
+ QueryStatement statement =
+ (QueryStatement) StatementGenerator.createStatement(sql,
ZonedDateTime.now().getOffset());
+ statement.semanticCheck();
+ }
+}