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/12/07 13:55:36 UTC

[iotdb] branch master updated: Update nodenames if necessary in ClientRpcServiceImpl (#8359)

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 a971a8d04f Update nodenames if necessary in ClientRpcServiceImpl (#8359)
a971a8d04f is described below

commit a971a8d04fb0c5c992582d01ee7ef5e17ebbb4e2
Author: Liao Lanyu <14...@qq.com>
AuthorDate: Wed Dec 7 21:55:31 2022 +0800

    Update nodenames if necessary in ClientRpcServiceImpl (#8359)
---
 .../session/it/IoTDBSessionSyntaxConventionIT.java |   2 +
 .../org/apache/iotdb/commons/utils/PathUtils.java  | 135 ++++++++++++---------
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |  14 +--
 .../service/thrift/impl/ClientRPCServiceImpl.java  |  32 +++--
 .../db/service/thrift/impl/TSServiceImpl.java      |  13 +-
 5 files changed, 110 insertions(+), 86 deletions(-)

diff --git a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSyntaxConventionIT.java b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSyntaxConventionIT.java
index 9b3a24160c..f0417d0500 100644
--- a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSyntaxConventionIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSyntaxConventionIT.java
@@ -109,6 +109,7 @@ public class IoTDBSessionSyntaxConventionIT {
       measurements.add("`a“(Φ)”b`");
       measurements.add("`a>b`");
       measurements.add("`\\\"a`");
+      measurements.add("`aaa`");
       List<String> values = new ArrayList<>();
 
       for (int i = 0; i < measurements.size(); i++) {
@@ -125,6 +126,7 @@ public class IoTDBSessionSyntaxConventionIT {
       assertTrue(session.checkTimeseriesExists("root.sg1.d1.`a“(Φ)”b`"));
       assertTrue(session.checkTimeseriesExists("root.sg1.d1.`a>b`"));
       assertTrue(session.checkTimeseriesExists("root.sg1.d1.`\\\"a`"));
+      assertTrue(session.checkTimeseriesExists("root.sg1.d1.aaa"));
     } catch (Exception e) {
       e.printStackTrace();
       fail(e.getMessage());
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/utils/PathUtils.java b/node-commons/src/main/java/org/apache/iotdb/commons/utils/PathUtils.java
index 3837424864..36f0050301 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/utils/PathUtils.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/utils/PathUtils.java
@@ -26,9 +26,10 @@ import org.apache.iotdb.tsfile.exception.PathParseException;
 import org.apache.iotdb.tsfile.read.common.parser.PathNodesGenerator;
 import org.apache.iotdb.tsfile.read.common.parser.PathVisitor;
 
-import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 public class PathUtils {
 
@@ -48,118 +49,131 @@ public class PathUtils {
     }
   }
 
-  public static void isLegalPath(String path) throws IllegalPathException {
+  public static String[] isLegalPath(String path) throws IllegalPathException {
     try {
-      PathNodesGenerator.splitPathToNodes(path);
+      return PathNodesGenerator.splitPathToNodes(path);
     } catch (PathParseException e) {
       throw new IllegalPathException(path);
     }
   }
 
   /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
-   * single node name
+   * check whether measurement is legal according to syntax convention. Measurement can only be a
+   * single node name. The returned list is updated, could be different from the original list.
    */
-  public static void isLegalSingleMeasurementLists(List<List<String>> measurementLists)
-      throws MetadataException {
+  public static List<List<String>> checkIsLegalSingleMeasurementListsAndUpdate(
+      List<List<String>> measurementLists) throws MetadataException {
     if (measurementLists == null) {
-      return;
+      return null;
     }
-    // use set to skip checking duplicated measurements
-    Set<String> measurementSet = new HashSet<>();
+    // skip checking duplicated measurements
+    Map<String, String> checkedMeasurements = new HashMap<>();
+    List<List<String>> res = new ArrayList<>();
     for (List<String> measurements : measurementLists) {
-      checkLegalSingleMeasurementsAndSkipDuplicate(measurements, measurementSet);
+      res.add(checkLegalSingleMeasurementsAndSkipDuplicate(measurements, checkedMeasurements));
     }
+    return res;
   }
 
   /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
+   * check whether measurement is legal according to syntax convention. Measurement can only be a
    * single node name, use set to skip checking duplicated measurements
    */
-  public static void checkLegalSingleMeasurementsAndSkipDuplicate(
-      List<String> measurements, Set<String> measurementSet) throws MetadataException {
+  public static List<String> checkLegalSingleMeasurementsAndSkipDuplicate(
+      List<String> measurements, Map<String, String> checkedMeasurements) throws MetadataException {
     if (measurements == null) {
-      return;
+      return null;
     }
+    List<String> res = new ArrayList<>();
     for (String measurement : measurements) {
       if (measurement == null) {
+        res.add(null);
         continue;
       }
-      if (measurementSet.contains(measurement)) {
+      if (checkedMeasurements.get(measurement) != null) {
+        res.add(checkedMeasurements.get(measurement));
         continue;
       }
-      measurementSet.add(measurement);
-      if (measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
-          && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
-        if (checkBackQuotes(measurement.substring(1, measurement.length() - 1))) {
-          continue;
-        } else {
-          throw new IllegalPathException(measurement);
-        }
-      }
-      if (IoTDBConstant.reservedWords.contains(measurement.toUpperCase())
-          || isRealNumber(measurement)
-          || !TsFileConstant.NODE_NAME_PATTERN.matcher(measurement).matches()) {
-        throw new IllegalPathException(measurement);
-      }
+      String checked = checkAndReturnSingleMeasurement(measurement);
+      checkedMeasurements.put(measurement, checked);
+      res.add(checked);
     }
+    return res;
   }
 
   /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
-   * single node name
+   * check whether measurement is legal according to syntax convention. Measurement can only be a
+   * single node name.
    */
-  public static void isLegalSingleMeasurements(List<String> measurements) throws MetadataException {
+  public static List<String> checkIsLegalSingleMeasurementsAndUpdate(List<String> measurements)
+      throws MetadataException {
     if (measurements == null) {
-      return;
+      return null;
     }
+    List<String> res = new ArrayList<>();
     for (String measurement : measurements) {
       if (measurement == null) {
         continue;
       }
-      if (measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
-          && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
-        if (checkBackQuotes(measurement.substring(1, measurement.length() - 1))) {
-          continue;
-        } else {
-          throw new IllegalPathException(measurement);
-        }
-      }
-      if (IoTDBConstant.reservedWords.contains(measurement.toUpperCase())
-          || isRealNumber(measurement)
-          || !TsFileConstant.NODE_NAME_PATTERN.matcher(measurement).matches()) {
-        throw new IllegalPathException(measurement);
-      }
+      res.add(checkAndReturnSingleMeasurement(measurement));
     }
+    return res;
   }
 
   /**
    * check whether measurement is legal according to syntax convention measurement could be like a.b
    * (more than one node name), in template?
    */
-  public static void isLegalMeasurementLists(List<List<String>> measurementLists)
-      throws IllegalPathException {
+  public static List<List<String>> checkIsLegalMeasurementListsAndUpdate(
+      List<List<String>> measurementLists) throws IllegalPathException {
     if (measurementLists == null) {
-      return;
+      return null;
     }
+    List<List<String>> res = new ArrayList<>();
     for (List<String> measurementList : measurementLists) {
-      isLegalMeasurements(measurementList);
+      res.add(checkIsLegalMeasurementsAndUpdate(measurementList));
     }
+    return res;
   }
 
   /**
    * check whether measurement is legal according to syntax convention measurement could be like a.b
    * (more than one node name), in template?
    */
-  public static void isLegalMeasurements(List<String> measurements) throws IllegalPathException {
+  public static List<String> checkIsLegalMeasurementsAndUpdate(List<String> measurements)
+      throws IllegalPathException {
     if (measurements == null) {
-      return;
+      return null;
     }
+    List<String> res = new ArrayList<>();
     for (String measurement : measurements) {
       if (measurement != null) {
-        PathUtils.isLegalPath(measurement);
+        res.add(PathUtils.isLegalPath(measurement)[0]);
       }
     }
+    return res;
+  }
+
+  /** check a measurement and update it if needed to. for example: `sd` -> sd */
+  public static String checkAndReturnSingleMeasurement(String measurement)
+      throws IllegalPathException {
+    if (measurement == null) {
+      return null;
+    }
+    if (measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
+        && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
+      if (checkBackQuotes(measurement.substring(1, measurement.length() - 1))) {
+        return removeBackQuotesIfNecessary(measurement);
+      } else {
+        throw new IllegalPathException(measurement);
+      }
+    }
+    if (IoTDBConstant.reservedWords.contains(measurement.toUpperCase())
+        || isRealNumber(measurement)
+        || !TsFileConstant.NODE_NAME_PATTERN.matcher(measurement).matches()) {
+      throw new IllegalPathException(measurement);
+    }
+    return measurement;
   }
 
   /** Return true if the str is a real number. Examples: 1.0; +1.0; -1.0; 0011; 011e3; +23e-3 */
@@ -171,6 +185,17 @@ public class PathUtils {
     return deviceName.equals(storageGroup) || deviceName.startsWith(storageGroup + ".");
   }
 
+  /** Remove the back quotes of a measurement if necessary */
+  public static String removeBackQuotesIfNecessary(String measurement) {
+    String unWrapped = measurement.substring(1, measurement.length() - 1);
+    if (PathUtils.isRealNumber(unWrapped)
+        || !TsFileConstant.IDENTIFIER_PATTERN.matcher(unWrapped).matches()) {
+      return measurement;
+    } else {
+      return unWrapped;
+    }
+  }
+
   private static boolean checkBackQuotes(String src) {
     int num = src.length() - src.replace("`", "").length();
     if (num % 2 == 1) {
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 83b72b2c37..23e897155a 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
@@ -1539,12 +1539,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
     }
     if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
         && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
-      String unWrapped = nodeName.substring(1, nodeName.length() - 1);
-      if (PathUtils.isRealNumber(unWrapped)
-          || !TsFileConstant.IDENTIFIER_PATTERN.matcher(unWrapped).matches()) {
-        return nodeName;
-      }
-      return unWrapped;
+      return PathUtils.removeBackQuotesIfNecessary(nodeName);
     }
     checkNodeName(nodeName);
     return nodeName;
@@ -1556,12 +1551,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
     }
     if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
         && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
-      String unWrapped = nodeName.substring(1, nodeName.length() - 1);
-      if (PathUtils.isRealNumber(unWrapped)
-          || !TsFileConstant.IDENTIFIER_PATTERN.matcher(unWrapped).matches()) {
-        return nodeName;
-      }
-      return unWrapped;
+      return PathUtils.removeBackQuotesIfNecessary(nodeName);
     }
     checkNodeNameInIntoPath(nodeName);
     return nodeName;
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java
index 0f1ef48f78..f3f9d4e5ba 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java
@@ -122,7 +122,6 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.time.ZoneId;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -599,7 +598,7 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // measurementAlias is also a nodeName
-      PathUtils.isLegalSingleMeasurements(Collections.singletonList(req.getMeasurementAlias()));
+      req.setMeasurementAlias(PathUtils.checkAndReturnSingleMeasurement(req.getMeasurementAlias()));
       // Step 1: transfer from TSCreateTimeseriesReq to Statement
       CreateTimeSeriesStatement statement =
           (CreateTimeSeriesStatement) StatementGenerator.createStatement(req);
@@ -647,9 +646,10 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurements(req.getMeasurementAlias());
+      req.setMeasurementAlias(
+          PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurementAlias()));
 
-      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
+      req.setMeasurements(PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurements()));
 
       // Step 1: transfer from CreateAlignedTimeSeriesReq to Statement
       CreateAlignedTimeSeriesStatement statement =
@@ -698,7 +698,8 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurements(req.getMeasurementAliasList());
+      req.setMeasurementAliasList(
+          PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurementAliasList()));
 
       // Step 1: transfer from CreateMultiTimeSeriesReq to Statement
       CreateMultiTimeSeriesStatement statement =
@@ -951,7 +952,8 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
+      req.setMeasurementsList(
+          PathUtils.checkIsLegalSingleMeasurementListsAndUpdate(req.getMeasurementsList()));
 
       // Step 1:  transfer from TSInsertRecordsReq to Statement
       InsertRowsStatement statement = (InsertRowsStatement) StatementGenerator.createStatement(req);
@@ -1006,7 +1008,8 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
+      req.setMeasurementsList(
+          PathUtils.checkIsLegalSingleMeasurementListsAndUpdate(req.getMeasurementsList()));
 
       // Step 1: transfer from TSInsertRecordsOfOneDeviceReq to Statement
       InsertRowsOfOneDeviceStatement statement =
@@ -1062,7 +1065,8 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
+      req.setMeasurementsList(
+          PathUtils.checkIsLegalSingleMeasurementListsAndUpdate(req.getMeasurementsList()));
 
       // Step 1: transfer from TSInsertStringRecordsOfOneDeviceReq to Statement
       InsertRowsOfOneDeviceStatement statement =
@@ -1119,7 +1123,7 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
           req.getTimestamp());
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
+      req.setMeasurements(PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurements()));
 
       InsertRowStatement statement = (InsertRowStatement) StatementGenerator.createStatement(req);
       // return success when this statement is empty because server doesn't need to execute it
@@ -1164,7 +1168,8 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
         return getNotLoggedInStatus();
       }
 
-      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
+      req.setMeasurementsList(
+          PathUtils.checkIsLegalSingleMeasurementListsAndUpdate(req.getMeasurementsList()));
 
       // Step 1: transfer from TSInsertTabletsReq to Statement
       InsertMultiTabletsStatement statement =
@@ -1212,7 +1217,7 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
+      req.setMeasurements(PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurements()));
       // Step 1: transfer from TSInsertTabletReq to Statement
       InsertTabletStatement statement =
           (InsertTabletStatement) StatementGenerator.createStatement(req);
@@ -1267,7 +1272,8 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
+      req.setMeasurementsList(
+          PathUtils.checkIsLegalSingleMeasurementListsAndUpdate(req.getMeasurementsList()));
 
       InsertRowsStatement statement = (InsertRowsStatement) StatementGenerator.createStatement(req);
       // return success when this statement is empty because server doesn't need to execute it
@@ -1731,7 +1737,7 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
           req.getTimestamp());
 
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
+      req.setMeasurements(PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurements()));
 
       InsertRowStatement statement = (InsertRowStatement) StatementGenerator.createStatement(req);
 
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java
index 901c96eefd..2a48fb5437 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java
@@ -1042,7 +1042,8 @@ public class TSServiceImpl implements IClientRPCServiceWithHandler {
       }
 
       // measurementAlias is also a nodeName
-      PathUtils.isLegalSingleMeasurements(Collections.singletonList(req.getMeasurementAlias()));
+      PathUtils.checkIsLegalSingleMeasurementsAndUpdate(
+          Collections.singletonList(req.getMeasurementAlias()));
       CreateTimeSeriesPlan plan =
           new CreateTimeSeriesPlan(
               new PartialPath(req.path),
@@ -1072,9 +1073,9 @@ public class TSServiceImpl implements IClientRPCServiceWithHandler {
 
       // check whether measurement is legal according to syntax convention
 
-      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurements());
 
-      PathUtils.isLegalSingleMeasurements(req.getMeasurementAlias());
+      PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.getMeasurementAlias());
 
       if (AUDIT_LOGGER.isDebugEnabled()) {
         AUDIT_LOGGER.debug(
@@ -1135,7 +1136,7 @@ public class TSServiceImpl implements IClientRPCServiceWithHandler {
 
       // measurementAlias is also a nodeName
 
-      PathUtils.isLegalSingleMeasurements(req.measurementAliasList);
+      PathUtils.checkIsLegalSingleMeasurementsAndUpdate(req.measurementAliasList);
 
       CreateMultiTimeSeriesPlan multiPlan = new CreateMultiTimeSeriesPlan();
       List<PartialPath> paths = new ArrayList<>(req.paths.size());
@@ -1255,7 +1256,7 @@ public class TSServiceImpl implements IClientRPCServiceWithHandler {
       ByteBuffer buffer = ByteBuffer.wrap(req.getSerializedTemplate());
       plan = CreateTemplatePlan.deserializeFromReq(buffer);
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalMeasurementLists(plan.getMeasurements());
+      PathUtils.checkIsLegalMeasurementListsAndUpdate(plan.getMeasurements());
       TSStatus status = SESSION_MANAGER.checkAuthority(plan, SESSION_MANAGER.getCurrSession());
 
       return status != null ? status : executeNonQueryPlan(plan);
@@ -1271,7 +1272,7 @@ public class TSServiceImpl implements IClientRPCServiceWithHandler {
   public TSStatus appendSchemaTemplate(TSAppendSchemaTemplateReq req) {
     try {
       // check whether measurement is legal according to syntax convention
-      PathUtils.isLegalMeasurements(req.getMeasurements());
+      PathUtils.checkIsLegalMeasurementsAndUpdate(req.getMeasurements());
     } catch (IoTDBException e) {
       onIoTDBException(e, OperationType.EXECUTE_NON_QUERY_PLAN, e.getErrorCode());
     }