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() {}
 }

Reply via email to