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 <[email protected]> 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() {} }
