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

jackietien pushed a commit to branch force_ci/object_type
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 65c96dfa445d65e81d9bd2c0883689f4f75d03ae
Author: Caideyipi <[email protected]>
AuthorDate: Mon Dec 8 11:43:33 2025 +0800

    Added name check to avoid directory attack (#16720)
    
    * partial
    
    * fix
    
    * part
    
    * createOrUpdate
    
    * partial
    
    * fix
    
    * partial
    
    * part
    
    * may_main_final
    
    * bug-fix
    
    * fix
    
    * Update StatementAnalyzer.java
    
    * fix
    
    * removal
    
    * object
    
    * fix-add-test
    
    * bug-fix
    
    * spotless
    
    * change-back
    
    * fix
    
    * change-name
    
    * fix
    
    * fix
    
    * partial_apply
    
    * fix
    
    * fix
    
    * fix
    
    * fix
    
    * fix
    
    * fix
    
    * remove-check
    
    * check_write
    
    * defense
    
    * unwebbed
    
    * clean
    
    * c
    
    * remove-useless-check
    
    * may-comp
    
    * qp
---
 .../iotdb/relational/it/schema/IoTDBTableIT.java   | 133 +++++++++++++++++++++
 .../manager/schema/ClusterSchemaManager.java       |  13 +-
 .../execution/config/TableConfigTaskVisitor.java   |  10 ++
 .../fetcher/TableDeviceSchemaValidator.java        |  23 ++--
 .../plan/relational/sql/ast/InsertRow.java         |  11 +-
 .../plan/relational/sql/ast/InsertRows.java        |  14 ++-
 .../plan/relational/sql/ast/InsertTablet.java      |   9 ++
 .../schemaregion/impl/SchemaRegionPBTreeImpl.java  |   2 +-
 .../apache/iotdb/commons/schema/table/TsTable.java |  31 +++++
 9 files changed, 233 insertions(+), 13 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
index 753ff5fa42b..1e95b05b05f 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
@@ -41,6 +41,9 @@ import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
@@ -777,6 +780,136 @@ public class IoTDBTableIT {
     }
   }
 
+  @Test
+  public void testTableObjectCheck() throws Exception {
+    final Set<String> illegal = new HashSet<>(Arrays.asList("./", ".", "..", 
".\\", "../hack"));
+    for (final String single : illegal) {
+      testObject4SingleIllegalPath(single);
+    }
+  }
+
+  private void testObject4SingleIllegalPath(final String illegal) throws 
Exception {
+    try (final Connection connection =
+            EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        final Statement statement = connection.createStatement();
+        final ITableSession session = 
EnvFactory.getEnv().getTableSessionConnection()) {
+      statement.execute("create database if not exists db2");
+      statement.execute("use db2");
+      statement.execute(String.format("create table \"%s\" ()", illegal));
+
+      try {
+        statement.execute(String.format("alter table \"%s\" add column a 
object", illegal));
+        fail();
+      } catch (final SQLException e) {
+        Assert.assertEquals(
+            String.format(
+                "701: When there are object fields, the tableName %s shall not 
be '.', '..' or contain './', '.\\'",
+                illegal),
+            e.getMessage());
+      }
+
+      // Test auto-create
+      String testObject =
+          System.getProperty("user.dir")
+              + File.separator
+              + "target"
+              + File.separator
+              + "test-classes"
+              + File.separator
+              + "ainode-example"
+              + File.separator
+              + "model.pt";
+
+      List<IMeasurementSchema> schemaList = new ArrayList<>();
+      schemaList.add(new MeasurementSchema("a", TSDataType.STRING));
+      schemaList.add(new MeasurementSchema("b", TSDataType.STRING));
+      schemaList.add(new MeasurementSchema("c", TSDataType.INT32));
+      schemaList.add(new MeasurementSchema(illegal, TSDataType.OBJECT));
+      final List<ColumnCategory> columnTypes =
+          Arrays.asList(
+              ColumnCategory.TAG,
+              ColumnCategory.ATTRIBUTE,
+              ColumnCategory.FIELD,
+              ColumnCategory.FIELD);
+      final Tablet tablet =
+          new Tablet(
+              illegal,
+              IMeasurementSchema.getMeasurementNameList(schemaList),
+              IMeasurementSchema.getDataTypeList(schemaList),
+              columnTypes,
+              1);
+      tablet.addTimestamp(0, System.currentTimeMillis());
+      tablet.addValue(schemaList.get(0).getMeasurementName(), 0, "d1");
+      tablet.addValue(schemaList.get(1).getMeasurementName(), 0, "a1");
+      tablet.addValue(schemaList.get(2).getMeasurementName(), 0, 0);
+      tablet.addValue(0, 3, true, 0, 
Files.readAllBytes(Paths.get(testObject)));
+
+      try {
+        session.executeNonQueryStatement("use db2");
+        session.insert(tablet);
+      } catch (final Exception e) {
+        Assert.assertEquals(
+            String.format(
+                "701: When there are object fields, the tableName %s shall not 
be '.', '..' or contain './', '.\\'",
+                illegal),
+            e.getMessage());
+      }
+
+      try {
+        statement.execute(String.format("create table test (\"%s\" object)", 
illegal));
+        fail();
+      } catch (final SQLException e) {
+        Assert.assertEquals(
+            String.format(
+                "701: When there are object fields, the objectName %s shall 
not be '.', '..' or contain './', '.\\'",
+                illegal),
+            e.getMessage());
+      }
+
+      statement.execute("create table test (a tag, b attribute, c int32, d 
object)");
+
+      // Cannot auto-extend illegal column
+      tablet.setTableName("test");
+      try {
+        session.executeNonQueryStatement("use db2");
+        session.insert(tablet);
+      } catch (final Exception e) {
+        Assert.assertEquals(
+            String.format(
+                "701: When there are object fields, the objectName %s shall 
not be '.', '..' or contain './', '.\\'",
+                illegal),
+            e.getMessage());
+      }
+
+      // It's OK if you don't write object
+      statement.execute(String.format("insert into test (a, b, c) values 
('%s', 1, 1)", illegal));
+      try {
+        statement.execute(
+            String.format("insert into test (a, b, c, d) values ('%s', 1, 1, 
's')", illegal));
+        fail();
+      } catch (final SQLException e) {
+        Assert.assertEquals(
+            String.format(
+                "507: When there are object fields, the deviceId [test, %s] 
shall not be '.', '..' or contain './', '.\\'",
+                illegal),
+            e.getMessage());
+      }
+
+      try {
+        statement.execute(String.format("alter table test add column \"%s\" 
object", illegal));
+        fail();
+      } catch (final SQLException e) {
+        Assert.assertEquals(
+            String.format(
+                "701: When there are object fields, the objectName %s shall 
not be '.', '..' or contain './', '.\\'",
+                illegal),
+            e.getMessage());
+      }
+
+      statement.execute("drop database db2");
+    }
+  }
+
   @Test
   public void testTreeViewTable() throws Exception {
     try (final Connection connection = EnvFactory.getEnv().getConnection();
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
index 9a04d9e9e59..a192511ffff 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
@@ -111,6 +111,7 @@ import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.tsfile.annotations.TableModel;
+import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.file.metadata.IDeviceID;
 import org.apache.tsfile.utils.Pair;
 import org.slf4j.Logger;
@@ -124,6 +125,7 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
@@ -1355,9 +1357,14 @@ public class ClusterSchemaManager {
             columnSchemaList.stream()
                 .map(TsTableColumnSchema::getColumnName)
                 .collect(Collectors.joining(", ")));
+
+    final AtomicBoolean hasObject = new AtomicBoolean(false);
     columnSchemaList.removeIf(
         columnSchema -> {
           if 
(Objects.isNull(originalTable.getColumnSchema(columnSchema.getColumnName()))) {
+            if (columnSchema.getDataType().equals(TSDataType.OBJECT)) {
+              hasObject.set(true);
+            }
             expandedTable.addColumnSchema(columnSchema);
             return false;
           }
@@ -1367,7 +1374,11 @@ public class ClusterSchemaManager {
     if (columnSchemaList.isEmpty()) {
       return new Pair<>(RpcUtils.getStatus(TSStatusCode.COLUMN_ALREADY_EXISTS, 
errorMsg), null);
     }
-    return new Pair<>(RpcUtils.SUCCESS_STATUS, expandedTable);
+
+    if (hasObject.get()) {
+      expandedTable.checkTableNameAndObjectNames4Object();
+    }
+    return new Pair<>(StatusUtils.OK, expandedTable);
   }
 
   public synchronized Pair<TSStatus, TsTable> 
tableColumnCheckForColumnRenaming(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
index bc52a3a7e8c..d659f30fc8f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.auth.entity.User;
 import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
 import org.apache.iotdb.commons.executable.ExecutableManager;
 import org.apache.iotdb.commons.path.PartialPath;
@@ -571,10 +572,12 @@ public class TableConfigTaskVisitor extends 
AstVisitor<IConfigTask, MPPQueryCont
     // TODO: Place the check at statement analyzer
     boolean hasTimeColumn = false;
     final Set<String> sourceNameSet = new HashSet<>();
+    boolean hasObject = false;
     for (final ColumnDefinition columnDefinition : node.getElements()) {
       final TsTableColumnCategory category = 
columnDefinition.getColumnCategory();
       final String columnName = columnDefinition.getName().getValue();
       final TSDataType dataType = getDataType(columnDefinition.getType());
+      hasObject |= dataType.equals(TSDataType.OBJECT);
       final String comment = columnDefinition.getComment();
       if (checkTimeColumnIdempotent(category, columnName, dataType, comment, 
table)
           && !hasTimeColumn) {
@@ -603,6 +606,13 @@ public class TableConfigTaskVisitor extends 
AstVisitor<IConfigTask, MPPQueryCont
       }
       table.addColumnSchema(schema);
     }
+    if (hasObject) {
+      try {
+        table.checkTableNameAndObjectNames4Object();
+      } catch (final MetadataException e) {
+        throw new SemanticException(e.getMessage(), e.getErrorCode());
+      }
+    }
     return new Pair<>(database, table);
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaValidator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaValidator.java
index b50a875d7b0..3be5d931657 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaValidator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaValidator.java
@@ -19,9 +19,9 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher;
 
-import org.apache.iotdb.commons.exception.IoTDBException;
-import org.apache.iotdb.db.conf.IoTDBConfig;
-import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
+import org.apache.iotdb.commons.schema.table.TsTable;
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import org.apache.iotdb.db.protocol.session.SessionManager;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.plan.Coordinator;
@@ -53,8 +53,6 @@ public class TableDeviceSchemaValidator {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(TableDeviceSchemaValidator.class);
 
-  private final IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
-
   private final Coordinator coordinator = Coordinator.getInstance();
 
   private final TableDeviceSchemaFetcher fetcher = 
TableDeviceSchemaFetcher.getInstance();
@@ -247,9 +245,18 @@ public class TableDeviceSchemaValidator {
             Long.MAX_VALUE,
             false);
     if (executionResult.status.getCode() != 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-      throw new RuntimeException(
-          new IoTDBException(
-              executionResult.status.getMessage(), 
executionResult.status.getCode()));
+      throw new IoTDBRuntimeException(
+          executionResult.status.getMessage(), 
executionResult.status.getCode());
+    }
+  }
+
+  public static void checkObject4DeviceId(final Object[] deviceId) {
+    for (final Object part : deviceId) {
+      final String value = (String) part;
+      if (Objects.nonNull(value) && TsTable.isInvalid4ObjectType(value)) {
+        throw new SemanticException(
+            TsTable.getObjectStringError("deviceId", 
Arrays.toString(deviceId)));
+      }
     }
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRow.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRow.java
index cbce78e6528..70b2e062365 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRow.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRow.java
@@ -21,11 +21,15 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
 
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.TableDeviceSchemaValidator;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
 
+import org.apache.tsfile.enums.TSDataType;
+
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 public class InsertRow extends WrappedInsertStatement {
 
@@ -56,7 +60,12 @@ public class InsertRow extends WrappedInsertStatement {
   @Override
   public List<Object[]> getDeviceIdList() {
     final InsertRowStatement insertRowStatement = getInnerTreeStatement();
-    Object[] segments = insertRowStatement.getTableDeviceID().getSegments();
+    final Object[] segments = 
insertRowStatement.getTableDeviceID().getSegments();
+    if (Objects.nonNull(getInnerTreeStatement().getMeasurementSchemas())
+        && Arrays.stream(getInnerTreeStatement().getMeasurementSchemas())
+            .anyMatch(schema -> Objects.nonNull(schema) && schema.getType() == 
TSDataType.OBJECT)) {
+      TableDeviceSchemaValidator.checkObject4DeviceId(segments);
+    }
     return Collections.singletonList(Arrays.copyOfRange(segments, 1, 
segments.length));
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
index d2a0da3c1dd..d35e68efcf5 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
@@ -25,13 +25,17 @@ import 
org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeUtils;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.ITableDeviceSchemaValidation;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.TableDeviceSchemaValidator;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
 
+import org.apache.tsfile.enums.TSDataType;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 public class InsertRows extends WrappedInsertStatement {
 
@@ -117,8 +121,14 @@ public class InsertRows extends WrappedInsertStatement {
 
       @Override
       public List<Object[]> getDeviceIdList() {
-        Object[] idSegments = 
insertRowStatement.getTableDeviceID().getSegments();
-        return Collections.singletonList(Arrays.copyOfRange(idSegments, 1, 
idSegments.length));
+        final Object[] tagSegments = 
insertRowStatement.getTableDeviceID().getSegments();
+        if (Objects.nonNull(insertRowStatement.getMeasurementSchemas())
+            && Arrays.stream(insertRowStatement.getMeasurementSchemas())
+                .anyMatch(
+                    schema -> Objects.nonNull(schema) && schema.getType() == 
TSDataType.OBJECT)) {
+          TableDeviceSchemaValidator.checkObject4DeviceId(tagSegments);
+        }
+        return Collections.singletonList(Arrays.copyOfRange(tagSegments, 1, 
tagSegments.length));
       }
 
       @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertTablet.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertTablet.java
index 9894adb4d01..8c1bccf28ab 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertTablet.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertTablet.java
@@ -21,8 +21,10 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
 
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.TableDeviceSchemaValidator;
 import 
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
 
+import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.file.metadata.IDeviceID;
 
 import java.util.ArrayList;
@@ -30,6 +32,7 @@ import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 public class InsertTablet extends WrappedInsertStatement {
 
@@ -65,6 +68,12 @@ public class InsertTablet extends WrappedInsertStatement {
     List<Object[]> deviceIdList = new ArrayList<>();
     for (IDeviceID deviceID : deviceID2LastIdxMap.keySet()) {
       Object[] segments = deviceID.getSegments();
+      if 
(Objects.nonNull(super.getInnerTreeStatement().getMeasurementSchemas())
+          && 
Arrays.stream(super.getInnerTreeStatement().getMeasurementSchemas())
+              .anyMatch(
+                  schema -> Objects.nonNull(schema) && schema.getType() == 
TSDataType.OBJECT)) {
+        TableDeviceSchemaValidator.checkObject4DeviceId(segments);
+      }
       deviceIdList.add(Arrays.copyOfRange(segments, 1, segments.length));
     }
     return deviceIdList;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
index a39b881fe1f..5a105cf7dd7 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
@@ -1548,7 +1548,7 @@ public class SchemaRegionPBTreeImpl implements 
ISchemaRegion {
 
   @Override
   public ISchemaReader<IDeviceSchemaInfo> getTableDeviceReader(
-      String table, List<Object[]> devicePathList) throws MetadataException {
+      String table, List<Object[]> devicePathList) {
     throw new UnsupportedOperationException();
   }
 
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
index 6c3d85c12aa..8336f0f4aa0 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.commons.schema.table;
 
 import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.exception.runtime.SchemaExecutionException;
 import org.apache.iotdb.commons.schema.table.column.AttributeColumnSchema;
 import org.apache.iotdb.commons.schema.table.column.FieldColumnSchema;
@@ -29,6 +30,7 @@ import 
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
 import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
 import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchemaUtil;
 import org.apache.iotdb.commons.utils.CommonDateTimeUtils;
+import org.apache.iotdb.rpc.TSStatusCode;
 
 import com.google.common.collect.ImmutableList;
 import org.apache.tsfile.enums.TSDataType;
@@ -69,6 +71,8 @@ public class TsTable {
 
   public static final String TTL_PROPERTY = "ttl";
   public static final Set<String> TABLE_ALLOWED_PROPERTIES = 
Collections.singleton(TTL_PROPERTY);
+  private static final String OBJECT_STRING_ERROR =
+      "When there are object fields, the %s %s shall not be '.', '..' or 
contain './', '.\\'";
   protected String tableName;
 
   private final Map<String, TsTableColumnSchema> columnSchemaMap = new 
LinkedHashMap<>();
@@ -410,6 +414,33 @@ public class TsTable {
     executeWrite(() -> this.props = props);
   }
 
+  public void checkTableNameAndObjectNames4Object() throws MetadataException {
+    if (isInvalid4ObjectType(tableName)) {
+      throw new MetadataException(
+          getObjectStringError("tableName", tableName),
+          TSStatusCode.SEMANTIC_ERROR.getStatusCode());
+    }
+    for (final TsTableColumnSchema schema : columnSchemaMap.values()) {
+      if (schema.getDataType().equals(TSDataType.OBJECT)
+          && isInvalid4ObjectType(schema.getColumnName())) {
+        throw new MetadataException(
+            getObjectStringError("objectName", schema.getColumnName()),
+            TSStatusCode.SEMANTIC_ERROR.getStatusCode());
+      }
+    }
+  }
+
+  public static boolean isInvalid4ObjectType(final String column) {
+    return column.equals(".")
+        || column.equals("..")
+        || column.contains("./")
+        || column.contains(".\\");
+  }
+
+  public static String getObjectStringError(final String columnType, final 
String columnName) {
+    return String.format(OBJECT_STRING_ERROR, columnType, columnName);
+  }
+
   @Override
   public boolean equals(Object o) {
     return super.equals(o);

Reply via email to