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 2022/09/13 09:54:34 UTC
[iotdb] 02/02: fix sql parser
This is an automated email from the ASF dual-hosted git repository.
hui pushed a commit to branch lmh/selectInto
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 55118b8b06d980b75e59a9410f5f1f13a834e525
Author: Minghui Liu <li...@foxmail.com>
AuthorDate: Tue Sep 13 17:54:01 2022 +0800
fix sql parser
---
.../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 11 +++-
.../antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 | 1 +
.../iotdb/db/mpp/plan/parser/ASTVisitor.java | 73 ++++++++++++++++------
.../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java | 20 +++---
.../tsfile/common/constant/TsFileConstant.java | 4 ++
5 files changed, 77 insertions(+), 32 deletions(-)
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 92eb4d018b..501fad06f7 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -385,12 +385,17 @@ intoClause
;
intoPath
- : fullPath
- | nodeNameWithoutWildcard (DOT nodeNameWithoutWildcard)*
+ : ROOT (DOT nodeNameInIntoPath)* #fullPathInIntoPath
+ | nodeNameInIntoPath (DOT nodeNameInIntoPath)* #suffixPathInIntoPath
;
intoDeviceAndMeasurement
- : intoPath LR_BRACKET nodeNameWithoutWildcard (DOT nodeNameWithoutWildcard)* RR_BRACKET
+ : intoPath LR_BRACKET nodeNameInIntoPath (COMMA nodeNameInIntoPath)* RR_BRACKET
+ ;
+
+nodeNameInIntoPath
+ : nodeNameWithoutWildcard
+ | DOUBLE_COLON
;
specialClause
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
index b30831d671..25ba54eac8 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
@@ -863,6 +863,7 @@ LR_BRACKET : '(';
RR_BRACKET : ')';
LS_BRACKET : '[';
RS_BRACKET : ']';
+DOUBLE_COLON: '::';
/**
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 2d45b13fc0..f1b6b9091c 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
@@ -1364,40 +1364,39 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
private void parseIntoClause(IoTDBSqlParser.IntoClauseContext ctx) {
boolean isAligned = ctx.ALIGNED() != null;
- if (ctx.intoPath() != null) {
- List<PartialPath> intoPaths = new ArrayList<>();
- for (IoTDBSqlParser.IntoPathContext intoPathContext : ctx.intoPath()) {
- intoPaths.add(parseIntoPath(intoPathContext));
- }
- queryStatement.setIntoComponent(new AlignByTimeIntoComponent(intoPaths, isAligned));
- } else if (ctx.intoDeviceAndMeasurement() != null) {
+ if (ctx.intoDeviceAndMeasurement().size() > 0) {
List<Pair<PartialPath, List<PartialPath>>> intoDeviceAndMeasurementList = new ArrayList<>();
for (IoTDBSqlParser.IntoDeviceAndMeasurementContext intoDeviceAndMeasurementContext :
ctx.intoDeviceAndMeasurement()) {
PartialPath intoDevice = parseIntoPath(intoDeviceAndMeasurementContext.intoPath());
List<PartialPath> intoMeasurements =
- intoDeviceAndMeasurementContext.nodeNameWithoutWildcard().stream()
+ intoDeviceAndMeasurementContext.nodeNameInIntoPath().stream()
.map(
- nodeNameWithoutWildcardContext ->
- new PartialPath(
- parseNodeNameWithoutWildCard(nodeNameWithoutWildcardContext), false))
+ nodeNameInIntoPathContext ->
+ new PartialPath(parseNodeNameInIntoPath(nodeNameInIntoPathContext), false))
.collect(Collectors.toList());
intoDeviceAndMeasurementList.add(new Pair<>(intoDevice, intoMeasurements));
}
queryStatement.setIntoComponent(
new AlignByDeviceIntoComponent(intoDeviceAndMeasurementList, isAligned));
+ } else {
+ List<PartialPath> intoPaths = new ArrayList<>();
+ for (IoTDBSqlParser.IntoPathContext intoPathContext : ctx.intoPath()) {
+ intoPaths.add(parseIntoPath(intoPathContext));
+ }
+ queryStatement.setIntoComponent(new AlignByTimeIntoComponent(intoPaths, isAligned));
}
}
private PartialPath parseIntoPath(IoTDBSqlParser.IntoPathContext intoPathContext) {
- if (intoPathContext.fullPath() != null) {
- return parseFullPath(intoPathContext.fullPath());
+ if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
+ return parseFullPathInIntoPath((IoTDBSqlParser.FullPathInIntoPathContext) intoPathContext);
} else {
- List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNames =
- intoPathContext.nodeNameWithoutWildcard();
+ List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames =
+ ((IoTDBSqlParser.SuffixPathInIntoPathContext) intoPathContext).nodeNameInIntoPath();
String[] path = new String[nodeNames.size()];
for (int i = 0; i < nodeNames.size(); i++) {
- path[i] = parseNodeNameWithoutWildCard(nodeNames.get(i));
+ path[i] = parseNodeNameInIntoPath(nodeNames.get(i));
}
return new PartialPath(path);
}
@@ -1524,6 +1523,20 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
return new PartialPath(path);
}
+ private PartialPath parseFullPathInIntoPath(IoTDBSqlParser.FullPathInIntoPathContext ctx) {
+ List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames = ctx.nodeNameInIntoPath();
+ String[] path = new String[nodeNames.size() + 1];
+ int i = 0;
+ if (ctx.ROOT() != null) {
+ path[0] = ctx.ROOT().getText();
+ }
+ for (IoTDBSqlParser.NodeNameInIntoPathContext nodeName : nodeNames) {
+ i++;
+ path[i] = parseNodeNameInIntoPath(nodeName);
+ }
+ return new PartialPath(path);
+ }
+
private PartialPath parsePrefixPath(IoTDBSqlParser.PrefixPathContext ctx) {
List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
String[] path = new String[nodeNames.size() + 1];
@@ -1548,11 +1561,24 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
}
private String parseNodeName(IoTDBSqlParser.NodeNameContext ctx) {
- return parseNodeString(ctx.getText());
+ String nodeName = parseNodeString(ctx.getText());
+ checkNodeName(nodeName);
+ return nodeName;
}
private String parseNodeNameWithoutWildCard(IoTDBSqlParser.NodeNameWithoutWildcardContext ctx) {
- return parseNodeString(ctx.getText());
+ String nodeName = parseNodeString(ctx.getText());
+ checkNodeName(nodeName);
+ return nodeName;
+ }
+
+ private String parseNodeNameInIntoPath(IoTDBSqlParser.NodeNameInIntoPathContext ctx) {
+ if (ctx.DOUBLE_COLON() != null) {
+ return ctx.getText();
+ }
+ String nodeName = parseNodeString(ctx.getText());
+ checkNodeNameInIntoPath(nodeName);
+ return nodeName;
}
private String parseNodeString(String nodeName) {
@@ -1569,7 +1595,6 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
}
return unWrapped;
}
- checkNodeName(nodeName);
return nodeName;
}
@@ -1583,6 +1608,16 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
}
}
+ private void checkNodeNameInIntoPath(String src) {
+ // ${} are allowed
+ if (!TsFileConstant.NODE_NAME_IN_INTO_PATH_PATTERN.matcher(src).matches()) {
+ throw new SQLParserException(
+ String.format(
+ "%s is illegal, unquoted node name in select into clause can only consist of digits, characters, $, { and }",
+ src));
+ }
+ }
+
private void checkIdentifier(String src) {
if (!TsFileConstant.IDENTIFIER_PATTERN.matcher(src).matches()) {
throw new SQLParserException(
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 0551aec282..1ca6715cc9 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -1304,8 +1304,9 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
}
PartialPath intoPath = null;
- if (intoPathContext.fullPath() != null) {
- intoPath = parseFullPathInSelectInto(intoPathContext.fullPath());
+ if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
+ intoPath =
+ parseFullPathInSelectInto((IoTDBSqlParser.FullPathInIntoPathContext) intoPathContext);
Matcher m = leveledPathNodePattern.matcher(intoPath.getFullPath());
while (m.find()) {
@@ -1321,9 +1322,9 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
"the x of ${x} should be greater than 0 and equal to or less than <level> or the length of queried path prefix.");
}
}
- } else if (intoPathContext.nodeNameWithoutWildcard() != null) {
- List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNameWithoutStars =
- intoPathContext.nodeNameWithoutWildcard();
+ } else if (intoPathContext instanceof IoTDBSqlParser.SuffixPathInIntoPathContext) {
+ List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNameWithoutStars =
+ ((IoTDBSqlParser.SuffixPathInIntoPathContext) intoPathContext).nodeNameInIntoPath();
String[] intoPathNodes =
new String[1 + levelLimitOfSourcePrefixPath + nodeNameWithoutStars.size()];
@@ -2569,15 +2570,14 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
return new PartialPath(path);
}
- private PartialPath parseFullPathInSelectInto(IoTDBSqlParser.FullPathContext ctx) {
- List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
- ctx.nodeNameWithoutWildcard();
+ private PartialPath parseFullPathInSelectInto(IoTDBSqlParser.FullPathInIntoPathContext ctx) {
+ List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNamesWithoutStar = ctx.nodeNameInIntoPath();
String[] path = new String[nodeNamesWithoutStar.size() + 1];
int i = 0;
if (ctx.ROOT() != null) {
path[0] = ctx.ROOT().getText();
}
- for (IoTDBSqlParser.NodeNameWithoutWildcardContext nodeNameWithoutStar : nodeNamesWithoutStar) {
+ for (IoTDBSqlParser.NodeNameInIntoPathContext nodeNameWithoutStar : nodeNamesWithoutStar) {
i++;
path[i] = parseNodeNameWithoutWildCardInSelectInto(nodeNameWithoutStar);
}
@@ -2646,7 +2646,7 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
/** in select into, $ and {} are allowed */
private String parseNodeNameWithoutWildCardInSelectInto(
- IoTDBSqlParser.NodeNameWithoutWildcardContext ctx) {
+ IoTDBSqlParser.NodeNameInIntoPathContext ctx) {
String nodeName = ctx.getText();
if (nodeName.equals(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)
|| nodeName.equals(IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD)) {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java
index 86ea19abcd..956a34a953 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java
@@ -44,5 +44,9 @@ public class TsFileConstant {
private static final String NODE_NAME_MATCHER = "(\\*{0,2}[a-zA-Z0-9_\\u2E80-\\u9FFF]+\\*{0,2})";
public static final Pattern NODE_NAME_PATTERN = Pattern.compile(NODE_NAME_MATCHER);
+ private static final String NODE_NAME_IN_INTO_PATH_MATCHER = "([a-zA-Z0-9_${}\\u2E80-\\u9FFF]+)";
+ public static final Pattern NODE_NAME_IN_INTO_PATH_PATTERN =
+ Pattern.compile(NODE_NAME_IN_INTO_PATH_MATCHER);
+
private TsFileConstant() {}
}