You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/05/29 07:00:22 UTC

[iotdb] branch master updated: [IOTDB-3300] Improve measurement check performance for session api (#6019)

This is an automated email from the ASF dual-hosted git repository.

rong 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 2226800133 [IOTDB-3300] Improve measurement check performance for session api (#6019)
2226800133 is described below

commit 2226800133e63e271240cb33fc67d4764ad2d0b7
Author: Liao Lanyu <48...@users.noreply.github.com>
AuthorDate: Sun May 29 15:00:17 2022 +0800

    [IOTDB-3300] Improve measurement check performance for session api (#6019)
---
 .../apache/iotdb/session/IoTDBSessionSimpleIT.java |  27 -----
 .../session/IoTDBSessionSyntaxConventionIT.java    |  65 ++++++++++--
 .../apache/iotdb/commons/conf/IoTDBConstant.java   |  11 ++
 .../org/apache/iotdb/commons/utils/PathUtils.java  |  86 +++++++++++++++
 .../thrift/impl/DataNodeTSIServiceImpl.java        | 115 +++-----------------
 .../db/service/thrift/impl/TSServiceImpl.java      | 117 +++------------------
 6 files changed, 182 insertions(+), 239 deletions(-)

diff --git a/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSimpleIT.java b/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSimpleIT.java
index ae285a908c..eff3f9cbea 100644
--- a/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSimpleIT.java
+++ b/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSimpleIT.java
@@ -91,33 +91,6 @@ public class IoTDBSessionSimpleIT {
     EnvironmentUtils.cleanEnv();
   }
 
-  @Test
-  public void testInsertByBlankStrAndInferType()
-      throws IoTDBConnectionException, StatementExecutionException {
-    session = new Session("127.0.0.1", 6667, "root", "root");
-    session.open();
-
-    String deviceId = "root.sg1.d1";
-    List<String> measurements = new ArrayList<>();
-    measurements.add("s1 ");
-
-    List<String> values = new ArrayList<>();
-    values.add("1.0");
-    session.insertRecord(deviceId, 1L, measurements, values);
-
-    String[] expected = new String[] {"root.sg1.d1.s1 "};
-
-    assertFalse(session.checkTimeseriesExists("root.sg1.d1.s1 "));
-    SessionDataSet dataSet = session.executeQueryStatement("show timeseries");
-    int i = 0;
-    while (dataSet.hasNext()) {
-      assertEquals(expected[i], dataSet.next().getFields().get(0).toString());
-      i++;
-    }
-
-    session.close();
-  }
-
   @Test
   public void testInsertPartialTablet()
       throws IoTDBConnectionException, StatementExecutionException {
diff --git a/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSyntaxConventionIT.java b/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSyntaxConventionIT.java
index 5a97eb6c30..5dfb297050 100644
--- a/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSyntaxConventionIT.java
+++ b/integration/src/test/java/org/apache/iotdb/session/IoTDBSessionSyntaxConventionIT.java
@@ -102,7 +102,7 @@ public class IoTDBSessionSyntaxConventionIT {
 
     measurements.add("`\"a“(Φ)”b\"`");
     measurements.add("`\"a>b\"`");
-    measurements.add("`'a.b'`");
+    measurements.add("```a.b```");
     measurements.add("`'a“(Φ)”b'`");
     measurements.add("`'a>b'`");
     measurements.add("`a“(Φ)”b`");
@@ -118,7 +118,7 @@ public class IoTDBSessionSyntaxConventionIT {
 
     Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.`\"a“(Φ)”b\"`"));
     Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.`\"a>b\"`"));
-    Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.`'a.b'`"));
+    Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.```a.b```"));
     Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.`'a“(Φ)”b'`"));
     Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.`'a>b'`"));
     Assert.assertTrue(session.checkTimeseriesExists("root.sg1.d1.`a“(Φ)”b`"));
@@ -136,16 +136,69 @@ public class IoTDBSessionSyntaxConventionIT {
 
     String deviceId = "root.sg1.d1";
     List<String> measurements = new ArrayList<>();
+    List<String> values = new ArrayList<>();
     measurements.add("a.b");
+    values.add("1");
+    try {
+      session.insertRecord(deviceId, 1L, measurements, values);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    measurements.clear();
+    values.clear();
     measurements.add("111");
+    values.add("1.2");
+    try {
+      session.insertRecord(deviceId, 1L, measurements, values);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    measurements.clear();
+    values.clear();
     measurements.add("`a");
+    values.add("1.2");
+    try {
+      session.insertRecord(deviceId, 1L, measurements, values);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    measurements.clear();
+    values.clear();
     measurements.add("a..b");
+    values.add("1.2");
+    try {
+      session.insertRecord(deviceId, 1L, measurements, values);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
 
-    List<String> values = new ArrayList<>();
-    values.add("1");
+    measurements.clear();
+    values.clear();
+    measurements.add("");
+    values.add("1.2");
+    try {
+      session.insertRecord(deviceId, 1L, measurements, values);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    measurements.clear();
+    values.clear();
+    measurements.add("`a``");
+    values.add("1.2");
+    try {
+      session.insertRecord(deviceId, 1L, measurements, values);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    measurements.clear();
+    values.clear();
+    measurements.add("`ab````");
     values.add("1.2");
-    values.add("true");
-    values.add("dad");
     try {
       session.insertRecord(deviceId, 1L, measurements, values);
     } catch (Exception e) {
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java b/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
index 3d0afc8d00..7e6190111f 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
@@ -18,6 +18,9 @@
  */
 package org.apache.iotdb.commons.conf;
 
+import java.util.HashSet;
+import java.util.Set;
+
 public class IoTDBConstant {
 
   private IoTDBConstant() {}
@@ -63,6 +66,14 @@ public class IoTDBConstant {
   public static final String MIN_TIME = "min_time";
   public static final String LAST_VALUE = "last_value";
   public static final int MIN_SUPPORTED_JDK_VERSION = 8;
+  public static final Set<String> reservedWords =
+      new HashSet<String>() {
+        {
+          add("TIME");
+          add("TIMESTAMP");
+          add("ROOT");
+        }
+      };
 
   // show info
   public static final String COLUMN_ITEM = "                             item";
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 941c7d2569..a886350498 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
@@ -18,10 +18,17 @@
  */
 package org.apache.iotdb.commons.utils;
 
+import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.exception.MetadataException;
+import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
 import org.apache.iotdb.tsfile.exception.PathParseException;
 import org.apache.iotdb.tsfile.read.common.parser.PathNodesGenerator;
 
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+
 public class PathUtils {
 
   /**
@@ -47,4 +54,83 @@ public class PathUtils {
       throw new IllegalPathException(path);
     }
   }
+
+  /**
+   * check whether measurement is legal according to syntax convention measurement can only be a
+   * single node name
+   */
+  public static void isLegalSingleMeasurementLists(List<List<String>> measurementLists)
+      throws MetadataException {
+    if (measurementLists == null) {
+      return;
+    }
+    for (List<String> measurements : measurementLists) {
+      isLegalMeasurements(measurements);
+    }
+  }
+
+  /**
+   * 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 {
+    if (measurements == null) {
+      return;
+    }
+    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())
+          || StringUtils.isNumeric(measurement)
+          || !TsFileConstant.NODE_NAME_PATTERN.matcher(measurement).matches()) {
+        throw new IllegalPathException(measurement);
+      }
+    }
+  }
+
+  /**
+   * 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 {
+    if (measurementLists == null) {
+      return;
+    }
+    for (List<String> measurementList : measurementLists) {
+      isLegalMeasurements(measurementList);
+    }
+  }
+
+  /**
+   * 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 {
+    if (measurements == null) {
+      return;
+    }
+    for (String measurement : measurements) {
+      if (measurement != null) {
+        PathUtils.isLegalPath(measurement);
+      }
+    }
+  }
+
+  private static boolean checkBackQuotes(String src) {
+    int num = src.length() - src.replace("`", "").length();
+    if (num % 2 == 1) {
+      return false;
+    }
+    return src.length() == (src.replace("``", "").length() + num);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java
index 7c3a5f6c9d..547e86dd6c 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeTSIServiceImpl.java
@@ -20,9 +20,7 @@ package org.apache.iotdb.db.service.thrift.impl;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
-import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.exception.IoTDBException;
-import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.utils.PathUtils;
 import org.apache.iotdb.db.auth.AuthorityChecker;
 import org.apache.iotdb.db.auth.AuthorizerManager;
@@ -101,7 +99,6 @@ import org.apache.iotdb.service.rpc.thrift.TSRawDataQueryReq;
 import org.apache.iotdb.service.rpc.thrift.TSSetSchemaTemplateReq;
 import org.apache.iotdb.service.rpc.thrift.TSSetTimeZoneReq;
 import org.apache.iotdb.service.rpc.thrift.TSUnsetSchemaTemplateReq;
-import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
 
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
@@ -332,7 +329,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // measurementAlias is also a nodeName
-      isLegalSingleMeasurements(Collections.singletonList(req.getMeasurementAlias()));
+      PathUtils.isLegalSingleMeasurements(Collections.singletonList(req.getMeasurementAlias()));
       // Step 1: transfer from TSCreateTimeseriesReq to Statement
       CreateTimeSeriesStatement statement =
           (CreateTimeSeriesStatement) StatementGenerator.createStatement(req);
@@ -390,9 +387,9 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurements(req.getMeasurementAlias());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurementAlias());
 
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
       // Step 1: transfer from CreateAlignedTimeSeriesReq to Statement
       CreateAlignedTimeSeriesStatement statement =
@@ -440,7 +437,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurements(req.getMeasurementAliasList());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurementAliasList());
 
       // Step 1: transfer from CreateMultiTimeSeriesReq to Statement
       CreateMultiTimeSeriesStatement statement =
@@ -646,7 +643,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurementLists(req.getMeasurementsList());
+      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
 
       // Step 1: TODO(INSERT) transfer from TSInsertTabletsReq to Statement
       InsertRowsStatement statement = (InsertRowsStatement) StatementGenerator.createStatement(req);
@@ -696,7 +693,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurementLists(req.getMeasurementsList());
+      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
 
       // Step 1: TODO(INSERT) transfer from TSInsertTabletsReq to Statement
       InsertRowsOfOneDeviceStatement statement =
@@ -747,7 +744,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurementLists(req.getMeasurementsList());
+      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
 
       // Step 1: TODO(INSERT) transfer from TSInsertTabletsReq to Statement
       InsertRowsOfOneDeviceStatement statement =
@@ -798,7 +795,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
           req.getTimestamp());
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
       InsertRowStatement statement = (InsertRowStatement) StatementGenerator.createStatement(req);
 
@@ -838,7 +835,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
         return getNotLoggedInStatus();
       }
 
-      isLegalSingleMeasurementLists(req.getMeasurementsList());
+      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
 
       // Step 1: TODO(INSERT) transfer from TSInsertTabletsReq to Statement
       InsertMultiTabletsStatement statement =
@@ -881,7 +878,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
       // Step 1: TODO(INSERT) transfer from TSInsertTabletReq to Statement
       InsertTabletStatement statement =
           (InsertTabletStatement) StatementGenerator.createStatement(req);
@@ -931,7 +928,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
       }
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurementLists(req.getMeasurementsList());
+      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
 
       InsertRowsStatement statement = (InsertRowsStatement) StatementGenerator.createStatement(req);
 
@@ -1184,7 +1181,7 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
           req.getTimestamp());
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
       InsertRowStatement statement = (InsertRowStatement) StatementGenerator.createStatement(req);
 
@@ -1272,92 +1269,4 @@ public class DataNodeTSIServiceImpl implements TSIEventHandler {
   private QueryId genQueryId(long id) {
     return new QueryId(String.valueOf(id));
   }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
-   * single node name
-   */
-  protected void isLegalSingleMeasurementLists(List<List<String>> measurementLists)
-      throws MetadataException {
-    if (measurementLists == null) {
-      return;
-    }
-    StringBuilder path = new StringBuilder(IoTDBConstant.PATH_ROOT);
-    for (List<String> measurementList : measurementLists) {
-      for (String measurement : measurementList) {
-        if (measurement != null) {
-          if (measurement.contains(TsFileConstant.PATH_SEPARATOR)
-              && !(measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
-                  && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING))) {
-            throw new IllegalPathException(measurement);
-          } else {
-            path.append(TsFileConstant.PATH_SEPARATOR);
-            path.append(measurement);
-          }
-        }
-      }
-    }
-    try {
-      PathUtils.isLegalPath(path.toString());
-    } catch (IllegalPathException e) {
-      throw new MetadataException("find wrong node name according to syntax convention");
-    }
-  }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
-   * single node name
-   */
-  protected void isLegalSingleMeasurements(List<String> measurements) throws MetadataException {
-    if (measurements == null) {
-      return;
-    }
-    StringBuilder path = new StringBuilder(IoTDBConstant.PATH_ROOT);
-    for (String measurement : measurements) {
-      if (measurement != null) {
-        if (measurement.contains(TsFileConstant.PATH_SEPARATOR)
-            && !(measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
-                && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING))) {
-          throw new IllegalPathException(measurement);
-        } else {
-          path.append(TsFileConstant.PATH_SEPARATOR);
-          path.append(measurement);
-        }
-      }
-    }
-    try {
-      PathUtils.isLegalPath(path.toString());
-    } catch (IllegalPathException e) {
-      throw new MetadataException("find wrong node name according to syntax convention");
-    }
-  }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement could be like a.b
-   * (more than one node name), in template?
-   */
-  protected void isLegalMeasurementLists(List<List<String>> measurementLists)
-      throws IllegalPathException {
-    if (measurementLists == null) {
-      return;
-    }
-    for (List<String> measurementList : measurementLists) {
-      isLegalMeasurements(measurementList);
-    }
-  }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement could be like a.b
-   * (more than one node name), in template?
-   */
-  protected void isLegalMeasurements(List<String> measurements) throws IllegalPathException {
-    if (measurements == null) {
-      return;
-    }
-    for (String measurement : measurements) {
-      if (measurement != null) {
-        PathUtils.isLegalPath(measurement);
-      }
-    }
-  }
 }
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 9c144c1f39..659698b997 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
@@ -122,7 +122,6 @@ import org.apache.iotdb.service.rpc.thrift.TSSetSchemaTemplateReq;
 import org.apache.iotdb.service.rpc.thrift.TSSetTimeZoneReq;
 import org.apache.iotdb.service.rpc.thrift.TSTracingInfo;
 import org.apache.iotdb.service.rpc.thrift.TSUnsetSchemaTemplateReq;
-import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
 import org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException;
 import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
@@ -1193,7 +1192,7 @@ public class TSServiceImpl implements TSIEventHandler {
     for (int i = 0; i < req.prefixPaths.size(); i++) {
       try {
         // check whether measurement is legal according to syntax convention
-        isLegalSingleMeasurements(req.getMeasurementsList().get(i));
+        PathUtils.isLegalSingleMeasurements(req.getMeasurementsList().get(i));
         InsertRowPlan plan =
             new InsertRowPlan(
                 new PartialPath(req.getPrefixPaths().get(i)),
@@ -1266,7 +1265,7 @@ public class TSServiceImpl implements TSIEventHandler {
     List<TSStatus> statusList = new ArrayList<>();
     try {
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurementLists(req.getMeasurementsList());
+      PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
       InsertRowsOfOneDevicePlan plan =
           new InsertRowsOfOneDevicePlan(
               new PartialPath(req.getPrefixPath()),
@@ -1317,7 +1316,7 @@ public class TSServiceImpl implements TSIEventHandler {
       InsertRowPlan plan = new InsertRowPlan();
       try {
         // check whether measurement is legal according to syntax convention
-        isLegalSingleMeasurements(req.getMeasurementsList().get(i));
+        PathUtils.isLegalSingleMeasurements(req.getMeasurementsList().get(i));
         plan.setDevicePath(new PartialPath(req.getPrefixPath()));
         plan.setTime(req.getTimestamps().get(i));
         addMeasurementAndValue(plan, req.getMeasurementsList().get(i), req.getValuesList().get(i));
@@ -1377,7 +1376,7 @@ public class TSServiceImpl implements TSIEventHandler {
       InsertRowPlan plan = new InsertRowPlan();
       try {
         // check whether measurement is legal according to syntax convention
-        isLegalSingleMeasurements(req.getMeasurementsList().get(i));
+        PathUtils.isLegalSingleMeasurements(req.getMeasurementsList().get(i));
         plan.setDevicePath(new PartialPath(req.getPrefixPaths().get(i)));
         plan.setTime(req.getTimestamps().get(i));
         addMeasurementAndValue(plan, req.getMeasurementsList().get(i), req.getValuesList().get(i));
@@ -1487,7 +1486,7 @@ public class TSServiceImpl implements TSIEventHandler {
 
       // check whether measurement is legal according to syntax convention
 
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
       InsertRowPlan plan =
           new InsertRowPlan(
@@ -1520,7 +1519,7 @@ public class TSServiceImpl implements TSIEventHandler {
           req.getTimestamp());
 
       // check whether measurement is legal according to syntax convention
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
       InsertRowPlan plan = new InsertRowPlan();
       plan.setDevicePath(new PartialPath(req.getPrefixPath()));
@@ -1576,7 +1575,7 @@ public class TSServiceImpl implements TSIEventHandler {
 
       // check whether measurement is legal according to syntax convention
 
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
       InsertTabletPlan insertTabletPlan =
           new InsertTabletPlan(new PartialPath(req.getPrefixPath()), req.measurements);
@@ -1627,7 +1626,7 @@ public class TSServiceImpl implements TSIEventHandler {
   private InsertTabletPlan constructInsertTabletPlan(TSInsertTabletsReq req, int i)
       throws MetadataException {
     // check whether measurement is legal according to syntax convention
-    isLegalSingleMeasurementLists(req.getMeasurementsList());
+    PathUtils.isLegalSingleMeasurementLists(req.getMeasurementsList());
     InsertTabletPlan insertTabletPlan =
         new InsertTabletPlan(new PartialPath(req.prefixPaths.get(i)), req.measurementsList.get(i));
     insertTabletPlan.setTimes(
@@ -1719,7 +1718,7 @@ public class TSServiceImpl implements TSIEventHandler {
       }
 
       // measurementAlias is also a nodeName
-      isLegalSingleMeasurements(Collections.singletonList(req.getMeasurementAlias()));
+      PathUtils.isLegalSingleMeasurements(Collections.singletonList(req.getMeasurementAlias()));
       CreateTimeSeriesPlan plan =
           new CreateTimeSeriesPlan(
               new PartialPath(req.path),
@@ -1760,9 +1759,9 @@ public class TSServiceImpl implements TSIEventHandler {
 
       // check whether measurement is legal according to syntax convention
 
-      isLegalSingleMeasurements(req.getMeasurements());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurements());
 
-      isLegalSingleMeasurements(req.getMeasurementAlias());
+      PathUtils.isLegalSingleMeasurements(req.getMeasurementAlias());
 
       if (AUDIT_LOGGER.isDebugEnabled()) {
         AUDIT_LOGGER.debug(
@@ -1823,7 +1822,7 @@ public class TSServiceImpl implements TSIEventHandler {
 
       // measurementAlias is also a nodeName
 
-      isLegalSingleMeasurements(req.measurementAliasList);
+      PathUtils.isLegalSingleMeasurements(req.measurementAliasList);
 
       CreateMultiTimeSeriesPlan multiPlan = new CreateMultiTimeSeriesPlan();
       List<PartialPath> paths = new ArrayList<>(req.paths.size());
@@ -1943,7 +1942,7 @@ public class TSServiceImpl implements TSIEventHandler {
       ByteBuffer buffer = ByteBuffer.wrap(req.getSerializedTemplate());
       plan = CreateTemplatePlan.deserializeFromReq(buffer);
       // check whether measurement is legal according to syntax convention
-      isLegalMeasurementLists(plan.getMeasurements());
+      PathUtils.isLegalMeasurementLists(plan.getMeasurements());
       TSStatus status = SESSION_MANAGER.checkAuthority(plan, req.getSessionId());
 
       return status != null ? status : executeNonQueryPlan(plan);
@@ -1959,7 +1958,7 @@ public class TSServiceImpl implements TSIEventHandler {
   public TSStatus appendSchemaTemplate(TSAppendSchemaTemplateReq req) {
     try {
       // check whether measurement is legal according to syntax convention
-      isLegalMeasurements(req.getMeasurements());
+      PathUtils.isLegalMeasurements(req.getMeasurements());
     } catch (IoTDBException e) {
       onIoTDBException(e, OperationType.EXECUTE_NON_QUERY_PLAN, e.getErrorCode());
     }
@@ -2136,92 +2135,4 @@ public class TSServiceImpl implements TSIEventHandler {
           .count(1, "operation_count", MetricLevel.IMPORTANT, "name", operation.getName());
     }
   }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
-   * single node name
-   */
-  protected void isLegalSingleMeasurementLists(List<List<String>> measurementLists)
-      throws MetadataException {
-    if (measurementLists == null) {
-      return;
-    }
-    StringBuilder path = new StringBuilder(IoTDBConstant.PATH_ROOT);
-    for (List<String> measurementList : measurementLists) {
-      for (String measurement : measurementList) {
-        if (measurement != null) {
-          if (measurement.contains(TsFileConstant.PATH_SEPARATOR)
-              && !(measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
-                  && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING))) {
-            throw new IllegalPathException(measurement);
-          } else {
-            path.append(TsFileConstant.PATH_SEPARATOR);
-            path.append(measurement);
-          }
-        }
-      }
-    }
-    try {
-      PathUtils.isLegalPath(path.toString());
-    } catch (IllegalPathException e) {
-      throw new MetadataException("find wrong node name according to syntax convention");
-    }
-  }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement can only be a
-   * single node name
-   */
-  protected void isLegalSingleMeasurements(List<String> measurements) throws MetadataException {
-    if (measurements == null) {
-      return;
-    }
-    StringBuilder path = new StringBuilder(IoTDBConstant.PATH_ROOT);
-    for (String measurement : measurements) {
-      if (measurement != null) {
-        if (measurement.contains(TsFileConstant.PATH_SEPARATOR)
-            && !(measurement.startsWith(TsFileConstant.BACK_QUOTE_STRING)
-                && measurement.endsWith(TsFileConstant.BACK_QUOTE_STRING))) {
-          throw new IllegalPathException(measurement);
-        } else {
-          path.append(TsFileConstant.PATH_SEPARATOR);
-          path.append(measurement);
-        }
-      }
-    }
-    try {
-      PathUtils.isLegalPath(path.toString());
-    } catch (IllegalPathException e) {
-      throw new MetadataException("find wrong node name according to syntax convention");
-    }
-  }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement could be like a.b
-   * (more than one node name), in template?
-   */
-  protected void isLegalMeasurementLists(List<List<String>> measurementLists)
-      throws IllegalPathException {
-    if (measurementLists == null) {
-      return;
-    }
-    for (List<String> measurementList : measurementLists) {
-      isLegalMeasurements(measurementList);
-    }
-  }
-
-  /**
-   * check whether measurement is legal according to syntax convention measurement could be like a.b
-   * (more than one node name), in template?
-   */
-  protected void isLegalMeasurements(List<String> measurements) throws IllegalPathException {
-    if (measurements == null) {
-      return;
-    }
-    for (String measurement : measurements) {
-      if (measurement != null) {
-        PathUtils.isLegalPath(measurement);
-      }
-    }
-  }
 }