This is an automated email from the ASF dual-hosted git repository.
jiangtian pushed a commit to branch force_ci/object_type
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/force_ci/object_type by this
push:
new 2bdba56dcb9 Added name check to avoid directory attack (#16720)
2bdba56dcb9 is described below
commit 2bdba56dcb91713e4861743fef2a0412aff2759d
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 c1c421ce57f..36dc53a4c41 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 417e65d4fe4..11d4c1aae18 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;
@@ -562,10 +563,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) {
@@ -594,6 +597,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);