You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by hu...@apache.org on 2023/02/28 06:45:18 UTC
[iotdb] branch master updated: [IOTDB-5592] Fix unexpected error when use full path in having/where (#9157)
This is an automated email from the ASF dual-hosted git repository.
hui 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 4ae7b3ab89 [IOTDB-5592] Fix unexpected error when use full path in having/where (#9157)
4ae7b3ab89 is described below
commit 4ae7b3ab8964e84103d2f8a8385821d34be551dd
Author: Weihao Li <60...@users.noreply.github.com>
AuthorDate: Tue Feb 28 14:45:12 2023 +0800
[IOTDB-5592] Fix unexpected error when use full path in having/where (#9157)
Signed-off-by: Weihao Li <18...@163.com>
---
.../apache/iotdb/db/it/path/IoTDBFullPathIT.java | 82 ++++++++++++++++++++++
.../iotdb/db/it/{ => path}/IoTDBQuotedPathIT.java | 2 +-
.../iotdb/db/mpp/plan/parser/ASTVisitor.java | 75 +++++++++-----------
3 files changed, 118 insertions(+), 41 deletions(-)
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/path/IoTDBFullPathIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/path/IoTDBFullPathIT.java
new file mode 100644
index 0000000000..a0d914919f
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/path/IoTDBFullPathIT.java
@@ -0,0 +1,82 @@
+/*
+ * 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.path;
+
+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.rpc.TSStatusCode;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+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.itbase.constant.TestConstant.TIMESTAMP_STR;
+import static org.apache.iotdb.itbase.constant.TestConstant.count;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBFullPathIT {
+ private static final String[] SQLs = new String[] {"INSERT INTO root.test(time,s1) VALUES(1,1)"};
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().getConfig().getCommonConfig().setPartitionInterval(1000);
+ EnvFactory.getEnv().initClusterEnvironment();
+ prepareData(SQLs);
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testUnsatisfiedRuleQuery() {
+ assertTestFail(
+ "select root.test.s1 from root.**",
+ TSStatusCode.SEMANTIC_ERROR.getStatusCode()
+ + ": Path can not start with root in select clause.");
+ }
+
+ @Test
+ public void testSatisfiedRuleQuery() {
+ String[] expectedHeader = new String[] {TIMESTAMP_STR, "root.test.s1"};
+ String[] retArray = new String[] {"1,1.0,"};
+ resultSetEqualTest(
+ "select s1 from root.** " + "where root.test.s1 is not null", expectedHeader, retArray);
+
+ resultSetEqualTest(
+ "select s1 from root.** " + "where root.test.s1 not in (2,3)", expectedHeader, retArray);
+
+ expectedHeader = new String[] {count("root.test.s1")};
+ retArray = new String[] {};
+ resultSetEqualTest(
+ "select count(s1) from root.** " + "having count(root.test.s1) not in (1,2)",
+ expectedHeader,
+ retArray);
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBQuotedPathIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/path/IoTDBQuotedPathIT.java
similarity index 99%
rename from integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBQuotedPathIT.java
rename to integration-test/src/test/java/org/apache/iotdb/db/it/path/IoTDBQuotedPathIT.java
index 5379bdf243..0c788782f2 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBQuotedPathIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/path/IoTDBQuotedPathIT.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.iotdb.db.it;
+package org.apache.iotdb.db.it.path;
import org.apache.iotdb.it.env.EnvFactory;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
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 08791b8217..dcb9d0d173 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
@@ -1133,8 +1133,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
// ---- Where Clause
private WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext ctx) {
- Expression predicate =
- parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == null);
+ Expression predicate = parseExpression(ctx.expression(), true);
return new WhereCondition(predicate);
}
@@ -1214,7 +1213,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
ExpressionContext expressionContext = expressions.get(0);
GroupByVariationComponent groupByVariationComponent = new GroupByVariationComponent();
groupByVariationComponent.setControlColumnExpression(
- parseExpression(expressionContext, expressionContext.OPERATOR_NOT() == null));
+ parseExpression(expressionContext, true));
groupByVariationComponent.setDelta(
ctx.delta == null ? 0 : Double.parseDouble(ctx.delta.getText()));
groupByVariationComponent.setIgnoringNull(ignoringNull);
@@ -1223,11 +1222,9 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
ExpressionContext conditionExpressionContext = expressions.get(0);
GroupBySeriesComponent groupBySeriesComponent = new GroupBySeriesComponent();
groupBySeriesComponent.setControlColumnExpression(
- parseExpression(
- conditionExpressionContext, conditionExpressionContext.OPERATOR_NOT() == null));
+ parseExpression(conditionExpressionContext, true));
if (expressions.size() == 2) {
- groupBySeriesComponent.setKeepExpression(
- parseExpression(expressions.get(1), expressions.get(1).OPERATOR_NOT() == null));
+ groupBySeriesComponent.setKeepExpression(parseExpression(expressions.get(1), true));
}
groupBySeriesComponent.setIgnoringNull(ignoringNull);
return groupBySeriesComponent;
@@ -1265,8 +1262,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
// ---- Having Clause
private HavingCondition parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx) {
- Expression predicate =
- parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == null);
+ Expression predicate = parseExpression(ctx.expression(), true);
return new HavingCondition(predicate);
}
@@ -1537,13 +1533,13 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
return new PartialPath(path);
}
- /** path of expression in withoutNull clause can start with root. */
private PartialPath parseFullPathInExpression(
- IoTDBSqlParser.FullPathInExpressionContext ctx, boolean inWithoutNull) {
+ IoTDBSqlParser.FullPathInExpressionContext ctx, boolean canUseFullPath) {
List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
int size = nodeNames.size();
if (ctx.ROOT() != null) {
- if (!inWithoutNull) {
+ if (!canUseFullPath) {
+ // now full path cannot occur in SELECT only
throw new SemanticException("Path can not start with root in select clause.");
}
size++;
@@ -2200,26 +2196,26 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
// Expression & Predicate ========================================================================
private Expression parseExpression(
- IoTDBSqlParser.ExpressionContext context, boolean inWithoutNull) {
+ IoTDBSqlParser.ExpressionContext context, boolean canUseFullPath) {
if (context.unaryInBracket != null) {
- return parseExpression(context.unaryInBracket, inWithoutNull);
+ return parseExpression(context.unaryInBracket, canUseFullPath);
}
if (context.expressionAfterUnaryOperator != null) {
if (context.MINUS() != null) {
return new NegationExpression(
- parseExpression(context.expressionAfterUnaryOperator, inWithoutNull));
+ parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
}
if (context.OPERATOR_NOT() != null) {
return new LogicNotExpression(
- parseExpression(context.expressionAfterUnaryOperator, inWithoutNull));
+ parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
}
- return parseExpression(context.expressionAfterUnaryOperator, inWithoutNull);
+ return parseExpression(context.expressionAfterUnaryOperator, canUseFullPath);
}
if (context.leftExpression != null && context.rightExpression != null) {
- Expression leftExpression = parseExpression(context.leftExpression, inWithoutNull);
- Expression rightExpression = parseExpression(context.rightExpression, inWithoutNull);
+ Expression leftExpression = parseExpression(context.leftExpression, canUseFullPath);
+ Expression rightExpression = parseExpression(context.rightExpression, canUseFullPath);
if (context.STAR() != null) {
return new MultiplicationExpression(leftExpression, rightExpression);
}
@@ -2264,24 +2260,24 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
if (context.unaryBeforeRegularOrLikeExpression != null) {
if (context.REGEXP() != null) {
- return parseRegularExpression(context, inWithoutNull);
+ return parseRegularExpression(context, canUseFullPath);
}
if (context.LIKE() != null) {
- return parseLikeExpression(context, inWithoutNull);
+ return parseLikeExpression(context, canUseFullPath);
}
throw new UnsupportedOperationException();
}
if (context.unaryBeforeIsNullExpression != null) {
- return parseIsNullExpression(context, inWithoutNull);
+ return parseIsNullExpression(context, canUseFullPath);
}
if (context.firstExpression != null
&& context.secondExpression != null
&& context.thirdExpression != null) {
- Expression firstExpression = parseExpression(context.firstExpression, inWithoutNull);
- Expression secondExpression = parseExpression(context.secondExpression, inWithoutNull);
- Expression thirdExpression = parseExpression(context.thirdExpression, inWithoutNull);
+ Expression firstExpression = parseExpression(context.firstExpression, canUseFullPath);
+ Expression secondExpression = parseExpression(context.secondExpression, canUseFullPath);
+ Expression thirdExpression = parseExpression(context.thirdExpression, canUseFullPath);
if (context.OPERATOR_BETWEEN() != null) {
return new BetweenExpression(
@@ -2291,16 +2287,16 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
}
if (context.unaryBeforeInExpression != null) {
- return parseInExpression(context, inWithoutNull);
+ return parseInExpression(context, canUseFullPath);
}
if (context.functionName() != null) {
- return parseFunctionExpression(context, inWithoutNull);
+ return parseFunctionExpression(context, canUseFullPath);
}
if (context.fullPathInExpression() != null) {
return new TimeSeriesOperand(
- parseFullPathInExpression(context.fullPathInExpression(), inWithoutNull));
+ parseFullPathInExpression(context.fullPathInExpression(), canUseFullPath));
}
if (context.time != null) {
@@ -2315,14 +2311,14 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
}
private Expression parseFunctionExpression(
- IoTDBSqlParser.ExpressionContext functionClause, boolean inWithoutNull) {
+ IoTDBSqlParser.ExpressionContext functionClause, boolean canUseFullPath) {
FunctionExpression functionExpression =
new FunctionExpression(parseIdentifier(functionClause.functionName().getText()));
// expressions
boolean hasNonPureConstantSubExpression = false;
for (IoTDBSqlParser.ExpressionContext expression : functionClause.expression()) {
- Expression subexpression = parseExpression(expression, inWithoutNull);
+ Expression subexpression = parseExpression(expression, canUseFullPath);
if (!subexpression.isConstantOperand()) {
hasNonPureConstantSubExpression = true;
}
@@ -2423,26 +2419,26 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
expressionString, actual, Arrays.toString(expected)));
}
- private Expression parseRegularExpression(ExpressionContext context, boolean inWithoutNull) {
+ private Expression parseRegularExpression(ExpressionContext context, boolean canUseFullPath) {
return new RegularExpression(
- parseExpression(context.unaryBeforeRegularOrLikeExpression, inWithoutNull),
+ parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
parseStringLiteral(context.STRING_LITERAL().getText()));
}
- private Expression parseLikeExpression(ExpressionContext context, boolean inWithoutNull) {
+ private Expression parseLikeExpression(ExpressionContext context, boolean canUseFullPath) {
return new LikeExpression(
- parseExpression(context.unaryBeforeRegularOrLikeExpression, inWithoutNull),
+ parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
parseStringLiteral(context.STRING_LITERAL().getText()));
}
- private Expression parseIsNullExpression(ExpressionContext context, boolean inWithoutNull) {
+ private Expression parseIsNullExpression(ExpressionContext context, boolean canUseFullPath) {
return new IsNullExpression(
- parseExpression(context.unaryBeforeIsNullExpression, inWithoutNull),
+ parseExpression(context.unaryBeforeIsNullExpression, canUseFullPath),
context.OPERATOR_NOT() != null);
}
- private Expression parseInExpression(ExpressionContext context, boolean inWithoutNull) {
- Expression childExpression = parseExpression(context.unaryBeforeInExpression, inWithoutNull);
+ private Expression parseInExpression(ExpressionContext context, boolean canUseFullPath) {
+ Expression childExpression = parseExpression(context.unaryBeforeInExpression, canUseFullPath);
LinkedHashSet<String> values = new LinkedHashSet<>();
for (ConstantContext constantContext : context.constant()) {
values.add(parseConstant(constantContext));
@@ -3051,8 +3047,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
// parse where
IoTDBSqlParser.WhereClauseContext whereCtx = ctx.whereClause();
if (whereCtx != null) {
- Expression predicate =
- parseExpression(whereCtx.expression(), whereCtx.expression().OPERATOR_NOT() == null);
+ Expression predicate = parseExpression(whereCtx.expression(), true);
if (!((predicate instanceof GreaterThanExpression)
|| (predicate instanceof GreaterEqualExpression))) {
throw new SemanticException(UNSUPPORTED_CLAUSE_IN_PIPE);