This is an automated email from the ASF dual-hosted git repository. jlfsdtc pushed a commit to branch kylin5 in repository https://gitbox.apache.org/repos/asf/kylin.git
The following commit(s) were added to refs/heads/kylin5 by this push: new b715b530e3 KYLIN-6076 Add tblproperties validation for InternalTable b715b530e3 is described below commit b715b530e344c81de8259cc93e3f8e36557d0b38 Author: jlf <1251489...@qq.com> AuthorDate: Wed Aug 27 18:41:25 2025 +0800 KYLIN-6076 Add tblproperties validation for InternalTable --- .../kylin/rest/request/InternalTableRequest.java | 4 +- .../org/apache/kylin/common/msg/CnMessage.java | 10 ++++ .../java/org/apache/kylin/common/msg/Message.java | 8 +++ .../org/apache/kylin/common/util/ArrayUtils.java | 28 +++++++++ .../kylin/metadata/cube/model/NBatchConstants.java | 29 +++++++++ .../kylin/metadata/table/InternalTableDesc.java | 51 ++++++++-------- .../metadata/table/InternalTableDescTest.java | 10 +++- .../rest/service/InternalTableServiceTest.java | 55 +++++++++++++++++ .../kylin/rest/service/InternalTableService.java | 68 ++++++++++++++++++++++ .../rest/controller/InternalTableController.java | 2 + 10 files changed, 239 insertions(+), 26 deletions(-) diff --git a/src/common-service/src/main/java/org/apache/kylin/rest/request/InternalTableRequest.java b/src/common-service/src/main/java/org/apache/kylin/rest/request/InternalTableRequest.java index 7335df38cd..6b1aede324 100644 --- a/src/common-service/src/main/java/org/apache/kylin/rest/request/InternalTableRequest.java +++ b/src/common-service/src/main/java/org/apache/kylin/rest/request/InternalTableRequest.java @@ -17,7 +17,7 @@ */ package org.apache.kylin.rest.request; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonProperty; @@ -36,7 +36,7 @@ public class InternalTableRequest { private String datePartitionFormat; @JsonProperty("tbl_properties") - private Map<String, String> tblProperties = new HashMap<>(); + private Map<String, String> tblProperties = new LinkedHashMap<>(); @JsonProperty("storage_type") private String storageType; diff --git a/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java b/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java index 3c2a8a953b..e457e5139f 100644 --- a/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java +++ b/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java @@ -1780,4 +1780,14 @@ public class CnMessage extends Message { public String getModelStorageUpdateFailed() { return "更新模型存储类型失败,请确认模型中没有 segment 后重试。"; } + + @Override + public String getInternalTableStorageTypeFailed() { + return "不支持的内表存储类型 %s,请检查后再重试。"; + } + + @Override + public String getInternalTableTblPropertiesFailed() { + return "不支持的内表表属性 %s,请检查后再重试。"; + } } diff --git a/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java b/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java index 9e11f10831..ef13e429d3 100644 --- a/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java +++ b/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java @@ -1625,4 +1625,12 @@ public class Message { public String getModelStorageUpdateFailed() { return "Update model storage failed, please make sure model not contain segment."; } + + public String getInternalTableStorageTypeFailed() { + return "Unsupported StorageType \"%s\", please check and try again."; + } + + public String getInternalTableTblPropertiesFailed() { + return "Unsupported tbl_properties parameter \"%s\", please check and try again."; + } } diff --git a/src/core-common/src/main/java/org/apache/kylin/common/util/ArrayUtils.java b/src/core-common/src/main/java/org/apache/kylin/common/util/ArrayUtils.java index 0894324ba0..caea69471c 100644 --- a/src/core-common/src/main/java/org/apache/kylin/common/util/ArrayUtils.java +++ b/src/core-common/src/main/java/org/apache/kylin/common/util/ArrayUtils.java @@ -35,4 +35,32 @@ public class ArrayUtils { } return result; } + + /** + * Checks if the given subset is a prefix of the superset. + * + * A subset is considered a prefix of the superset if: + * 1. The subset is shorter than or equal to the superset in length. + * 2. All elements in the subset match the corresponding elements in the superset at the same positions. + * + * Examples: + * - subset = ["a", "b"], superset = ["a", "b", "c"] -> returns true + * - subset = ["a", "b"], superset = ["a", "c", "b"] -> returns false + * - subset = ["a", "b", "c"], superset = ["a", "b"] -> returns false + * + * @param subset The list to check if it is a prefix subset. + * @param superset The list to check against (the larger list). + * @return True if the subset is a prefix of the superset, otherwise false. + */ + public static boolean isPrefixSubset(List<String> subset, List<String> superset) { + if (subset.size() > superset.size()) { + return false; + } + for (int i = 0; i < subset.size(); i++) { + if (!subset.get(i).equals(superset.get(i))) { + return false; + } + } + return true; + } } diff --git a/src/core-metadata/src/main/java/org/apache/kylin/metadata/cube/model/NBatchConstants.java b/src/core-metadata/src/main/java/org/apache/kylin/metadata/cube/model/NBatchConstants.java index 415e59f1a9..fab3fab21a 100644 --- a/src/core-metadata/src/main/java/org/apache/kylin/metadata/cube/model/NBatchConstants.java +++ b/src/core-metadata/src/main/java/org/apache/kylin/metadata/cube/model/NBatchConstants.java @@ -18,6 +18,8 @@ package org.apache.kylin.metadata.cube.model; +import lombok.Getter; + public interface NBatchConstants { String P_DATAFLOW_ID = "dataflowId"; String P_SEGMENT_IDS = "segmentIds"; @@ -68,8 +70,12 @@ public interface NBatchConstants { String P_END_DATE = "endTime"; String P_PRIMARY_KEY = "primaryKey"; String P_ORDER_BY_KEY = "orderByKey"; + String P_BUCKET_COLUMN = "bucketCol"; + String P_BUCKET_NUM = "bucketNum"; String P_DELETE_PARTITION_VALUES = "deletePartitionValues"; String P_DELETE_PARTITION = "deletePartition"; + String P_SORT_BY_PARTITION_BEFORE_SAVE = "sortByPartition"; + String P_PRELOADED_CACHE = "preloadedCache"; /** index planner job parameters */ @@ -83,4 +89,27 @@ public interface NBatchConstants { // ut only String P_BREAK_POINT_LAYOUTS = "breakPointLayouts"; + + @Getter + enum TblPropertyKey { + PRIMARY_KEY(P_PRIMARY_KEY), + ORDER_BY_KEY(P_ORDER_BY_KEY), + BUCKET_COLUMN(P_BUCKET_COLUMN), + BUCKET_NUM(P_BUCKET_NUM); + + private final String value; + + TblPropertyKey(String value) { + this.value = value; + } + + public static boolean contains(String key) { + for (TblPropertyKey propertyKey : values()) { + if (propertyKey.getValue().equals(key)) { + return true; + } + } + return false; + } + } } diff --git a/src/core-metadata/src/main/java/org/apache/kylin/metadata/table/InternalTableDesc.java b/src/core-metadata/src/main/java/org/apache/kylin/metadata/table/InternalTableDesc.java index 93edb409dd..2bb0e5df6c 100644 --- a/src/core-metadata/src/main/java/org/apache/kylin/metadata/table/InternalTableDesc.java +++ b/src/core-metadata/src/main/java/org/apache/kylin/metadata/table/InternalTableDesc.java @@ -18,6 +18,13 @@ package org.apache.kylin.metadata.table; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_BUCKET_COLUMN; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_BUCKET_NUM; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_ORDER_BY_KEY; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_PRELOADED_CACHE; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_PRIMARY_KEY; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_SORT_BY_PARTITION_BEFORE_SAVE; + import java.io.Serializable; import java.util.Arrays; import java.util.List; @@ -48,12 +55,6 @@ import lombok.Setter; @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE) public class InternalTableDesc extends ATable implements Serializable { - private static final String BUCKET_COLUMN = "bucketCol"; - private static final String BUCKET_NUM = "bucketNum"; - private static final String PRELOADED_CACHE = "preloadedCache"; - private static final String PRIMARY_KEY = "primaryKey"; - private static final String SORT_BY_KEY = "sortByKey"; - private static final String SORT_BY_PARTITION_BEFORE_SAVE = "sortByPartition"; public static final int INIT_SIZE = 0; @Getter @@ -68,6 +69,15 @@ public class InternalTableDesc extends ATable implements Serializable { StorageType(String format) { this.format = format; } + + public static boolean contains(String format) { + for (StorageType storageType : StorageType.values()) { + if (storageType.name().equalsIgnoreCase(format)) { + return true; + } + } + return false; + } } @JsonProperty("tbl_properties") @@ -97,7 +107,6 @@ public class InternalTableDesc extends ATable implements Serializable { @JsonProperty("table_partition") private InternalTablePartition tablePartition; - public InternalTableDesc(InternalTableDesc other) { this.project = other.project; this.database.setName(other.getDatabase()); @@ -150,47 +159,43 @@ public class InternalTableDesc extends ATable implements Serializable { } public void setStorageType(String storageType) { - if (storageType == null) { - this.storageType = StorageType.GLUTEN; - } else { - String storageTypeUpper = storageType.toUpperCase(Locale.ROOT); - this.storageType = StorageType.valueOf(storageTypeUpper); - } + String storageTypeUpper = storageType.toUpperCase(Locale.ROOT); + this.storageType = StorageType.valueOf(storageTypeUpper); } public String getBucketColumn() { - if (null == tblProperties.get(BUCKET_COLUMN)) { + if (null == tblProperties.get(P_BUCKET_COLUMN)) { return null; } else { - return tblProperties.get(BUCKET_COLUMN).trim(); + return tblProperties.get(P_BUCKET_COLUMN).trim(); } } public int getBucketNumber() { - if (null == tblProperties.get(BUCKET_NUM)) { + if (null == tblProperties.get(P_BUCKET_NUM)) { return 0; } else { - return Integer.parseInt(tblProperties.get(BUCKET_NUM).trim()); + return Integer.parseInt(tblProperties.get(P_BUCKET_NUM).trim()); } } public List<String> getPrimaryKey() { - return Arrays.stream(StringUtils.split(tblProperties.get(PRIMARY_KEY), ",")).map(String::trim) + return Arrays.stream(StringUtils.split(tblProperties.get(P_PRIMARY_KEY), ",")).map(String::trim) .collect(Collectors.toList()); } - public List<String> getSortByKey() { - return Arrays.stream(StringUtils.split(tblProperties.get(SORT_BY_KEY), ",")).map(String::trim) + public List<String> getOrderByKey() { + return Arrays.stream(StringUtils.split(tblProperties.get(P_ORDER_BY_KEY), ",")).map(String::trim) .collect(Collectors.toList()); } public boolean isPreloadedCacheEnable() { - return Boolean.parseBoolean(tblProperties.getOrDefault(PRELOADED_CACHE, KylinConfig.FALSE)); + return Boolean.parseBoolean(tblProperties.getOrDefault(P_PRELOADED_CACHE, KylinConfig.FALSE)); } public boolean isSortByPartitionEnabled() { - if (tblProperties.containsKey(SORT_BY_PARTITION_BEFORE_SAVE)) { - return Boolean.parseBoolean(tblProperties.get(SORT_BY_PARTITION_BEFORE_SAVE)); + if (tblProperties.containsKey(P_SORT_BY_PARTITION_BEFORE_SAVE)) { + return Boolean.parseBoolean(tblProperties.get(P_SORT_BY_PARTITION_BEFORE_SAVE)); } else { return NProjectManager.getProjectConfig(project).isInternalTableSortByPartitionEnabled(); } diff --git a/src/core-metadata/src/test/java/org/apache/kylin/metadata/table/InternalTableDescTest.java b/src/core-metadata/src/test/java/org/apache/kylin/metadata/table/InternalTableDescTest.java index b4237f94a2..9d7e732a38 100644 --- a/src/core-metadata/src/test/java/org/apache/kylin/metadata/table/InternalTableDescTest.java +++ b/src/core-metadata/src/test/java/org/apache/kylin/metadata/table/InternalTableDescTest.java @@ -37,7 +37,7 @@ class InternalTableDescTest { TableDesc originTable = tableMetadataManager.getTableDesc("DEFAULT.TEST_KYLIN_FACT"); InternalTableDesc table = new InternalTableDesc(originTable); - table.setStorageType(null); + table.setStorageType(InternalTableDesc.StorageType.GLUTEN.name()); Assertions.assertEquals(InternalTableDesc.StorageType.GLUTEN, table.getStorageType()); table.setStorageType(InternalTableDesc.StorageType.PARQUET.name()); Assertions.assertEquals(InternalTableDesc.StorageType.PARQUET, table.getStorageType()); @@ -99,4 +99,12 @@ class InternalTableDescTest { table.optimizeTblProperties(); Assertions.assertTrue(table.isSortByPartitionEnabled()); } + + @Test + void testStorageType() { + String format = "clickhouse"; + Assertions.assertFalse(InternalTableDesc.StorageType.contains(format)); + format = "gluten"; + Assertions.assertTrue(InternalTableDesc.StorageType.contains(format)); + } } diff --git a/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/InternalTableServiceTest.java b/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/InternalTableServiceTest.java index b22e2c7d57..3cda8cac17 100644 --- a/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/InternalTableServiceTest.java +++ b/src/data-loading-service/src/test/java/org/apache/kylin/rest/service/InternalTableServiceTest.java @@ -19,6 +19,8 @@ package org.apache.kylin.rest.service; import static org.apache.kylin.common.exception.QueryErrorCode.EMPTY_TABLE; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_ORDER_BY_KEY; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_PRIMARY_KEY; import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -30,7 +32,9 @@ import static org.mockito.Mockito.when; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -65,6 +69,7 @@ import org.apache.kylin.metadata.table.InternalTableManager; import org.apache.kylin.metadata.table.InternalTablePartition; import org.apache.kylin.metadata.table.InternalTablePartitionDetail; import org.apache.kylin.rest.constant.Constant; +import org.apache.kylin.rest.request.InternalTableRequest; import org.apache.kylin.rest.response.InternalTableDescResponse; import org.apache.kylin.rest.response.InternalTableLoadingJobResponse; import org.apache.kylin.rest.util.AclEvaluate; @@ -1157,4 +1162,54 @@ public class InternalTableServiceTest extends AbstractTestCase { Assertions.assertEquals(kylinException.getErrorCode(), ServerErrorCode.INTERNAL_TABLE_NOT_EXIST.toErrorCode()); Assertions.assertFalse(internalTableFolder.exists()); } + + @Test + void testValidate() { + // 1. Unsupported StorageType + InternalTableRequest request = new InternalTableRequest(); + request.setStorageType("clickhouse"); + request.setTblProperties(Collections.emptyMap()); + Assertions.assertThrows(KylinException.class, () -> InternalTableService.validate(request)); + + // 2. Only check when storageType is GLUTEN + request.setStorageType(InternalTableDesc.StorageType.PARQUET.name()); + InternalTableService.validate(request); + + // 3. Unsupported tbl_properties parameter + Map<String, String> tblProperties = new LinkedHashMap<>(); + tblProperties.put("checkFalse", null); + request.setStorageType(InternalTableDesc.StorageType.GLUTEN.name()); + request.setTblProperties(tblProperties); + Assertions.assertThrows(KylinException.class, () -> InternalTableService.validate(request)); + + // 4. Skip check for cases that do not contain PRIMARY_KEY + tblProperties.clear(); + tblProperties.put(P_ORDER_BY_KEY, null); + InternalTableService.validate(request); + + // 5. Set PRIMARY_KEY without ORDER_BY_KEY + tblProperties.clear(); + tblProperties.put(P_PRIMARY_KEY, "primary1"); + Assertions.assertThrows(KylinException.class, () -> InternalTableService.validate(request)); + + // 6. Skip check for cases that set ORDER_BY_KEY without PRIMARY_KEY + tblProperties.clear(); + tblProperties.put(P_ORDER_BY_KEY, "order1"); + InternalTableService.validate(request); + + // 7. Test primaryKey is a prefix subset of orderByKey + tblProperties.clear(); + tblProperties.put(P_PRIMARY_KEY, "a,b"); + tblProperties.put(P_ORDER_BY_KEY, "a,b,c"); + InternalTableService.validate(request); + request.setStorageType(null); + InternalTableService.validate(request); + + // 8. Test primaryKey is not a prefix subset of orderByKey + tblProperties.clear(); + request.setStorageType(""); + tblProperties.put(P_PRIMARY_KEY, "a,c"); + tblProperties.put(P_ORDER_BY_KEY, "a,b,c"); + Assertions.assertThrows(KylinException.class, () -> InternalTableService.validate(request)); + } } diff --git a/src/datasource-service/src/main/java/org/apache/kylin/rest/service/InternalTableService.java b/src/datasource-service/src/main/java/org/apache/kylin/rest/service/InternalTableService.java index 5cd095a032..4496ac5a0f 100644 --- a/src/datasource-service/src/main/java/org/apache/kylin/rest/service/InternalTableService.java +++ b/src/datasource-service/src/main/java/org/apache/kylin/rest/service/InternalTableService.java @@ -24,6 +24,10 @@ import static org.apache.kylin.common.exception.ServerErrorCode.INTERNAL_TABLE_N import static org.apache.kylin.common.exception.ServerErrorCode.INTERNAL_TABLE_RELOAD_ERROR; import static org.apache.kylin.common.exception.ServerErrorCode.INVALID_INTERNAL_TABLE_PARAMETER; import static org.apache.kylin.common.exception.ServerErrorCode.TABLE_NOT_EXIST; +import static org.apache.kylin.common.util.ArrayUtils.isPrefixSubset; +import static org.apache.kylin.common.util.StringHelper.splitAndTrim; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_ORDER_BY_KEY; +import static org.apache.kylin.metadata.cube.model.NBatchConstants.P_PRIMARY_KEY; import java.io.IOException; import java.util.ArrayList; @@ -41,6 +45,7 @@ import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.exception.KylinException; +import org.apache.kylin.common.msg.Message; import org.apache.kylin.common.msg.MsgPicker; import org.apache.kylin.common.util.HadoopUtil; import org.apache.kylin.engine.spark.builder.InternalTableLoader; @@ -48,6 +53,7 @@ import org.apache.kylin.guava30.shaded.common.collect.Lists; import org.apache.kylin.guava30.shaded.common.collect.Maps; import org.apache.kylin.job.execution.ExecutableManager; import org.apache.kylin.job.execution.JobTypeEnum; +import org.apache.kylin.metadata.cube.model.NBatchConstants; import org.apache.kylin.metadata.model.ColumnDesc; import org.apache.kylin.metadata.model.NTableMetadataManager; import org.apache.kylin.metadata.model.TableDesc; @@ -56,6 +62,7 @@ import org.apache.kylin.metadata.table.InternalTableDesc; import org.apache.kylin.metadata.table.InternalTableManager; import org.apache.kylin.metadata.table.InternalTablePartition; import org.apache.kylin.metadata.table.InternalTablePartitionDetail; +import org.apache.kylin.rest.request.InternalTableRequest; import org.apache.kylin.rest.response.InternalTableDescResponse; import org.apache.kylin.rest.response.InternalTableLoadingJobResponse; import org.apache.kylin.rest.util.AclEvaluate; @@ -438,4 +445,65 @@ public class InternalTableService extends BasicService { return internalTableDesc.getTablePartition().getPartitionDetails(); } + public static void validate(InternalTableRequest request) { + String storageType = request.getStorageType(); + Message msg = MsgPicker.getMsg(); + // 1. Validate the legality of storageType + if (storageType == null || storageType.isEmpty()) { + request.setStorageType(InternalTableDesc.StorageType.GLUTEN.name()); + storageType = request.getStorageType(); + } + if (!InternalTableDesc.StorageType.contains(storageType)) { + throw new KylinException(INVALID_INTERNAL_TABLE_PARAMETER, + String.format(Locale.ROOT, msg.getInternalTableStorageTypeFailed(), storageType)); + } + + // 2. Skip subsequent checks if the type is not GLUTEN + // TODO check other storageType + if (!storageType.equalsIgnoreCase(InternalTableDesc.StorageType.GLUTEN.name())) { + return; + } + + // 3. Extract and validate key-value pairs + Map<String, String> tblProperties = request.getTblProperties(); + String primaryKey = null; + String orderByKey = null; + // 3.1 Iterate to check the validity of keys and extract target key values + for (Map.Entry<String, String> entry : tblProperties.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + // Check if the key is valid + if (!NBatchConstants.TblPropertyKey.contains(key)) { + throw new KylinException(INVALID_INTERNAL_TABLE_PARAMETER, + String.format(Locale.ROOT, msg.getInternalTableTblPropertiesFailed(), key)); + } + // Extract target key values + if (key.equals(P_PRIMARY_KEY)) { + primaryKey = value; + } + if (key.equals(P_ORDER_BY_KEY)) { + orderByKey = value; + } + } + // 4. Validate the existence of the primaryKey + if (primaryKey == null) { + return; + } + // 5. Ensure that the orderByKey is set + if (orderByKey == null) { + throw new KylinException(INVALID_INTERNAL_TABLE_PARAMETER, + "When " + P_PRIMARY_KEY + " is set, " + P_ORDER_BY_KEY + " must be set."); + } + // 6. Parse the field list + List<String> primaryColumns = Arrays.asList(splitAndTrim(primaryKey, ",")); + List<String> orderByColumns = Arrays.asList(splitAndTrim((orderByKey), ",")); + + // 7. Verify that the primaryKey is a prefix of the orderByKey + if (!isPrefixSubset(primaryColumns, orderByColumns)) { + throw new KylinException(INVALID_INTERNAL_TABLE_PARAMETER, + P_PRIMARY_KEY + " must be a prefix subset of " + P_ORDER_BY_KEY + ". Example: If " + P_ORDER_BY_KEY + + " is 'a,b,c', " + P_PRIMARY_KEY + " can be 'a', 'a,b' or 'a,b,c'"); + } + } + } diff --git a/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/InternalTableController.java b/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/InternalTableController.java index 1f5d87fa8b..595f0723fd 100644 --- a/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/InternalTableController.java +++ b/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/InternalTableController.java @@ -71,6 +71,7 @@ public class InternalTableController extends NBasicController { if (StringUtils.isBlank(table) || StringUtils.isBlank(database)) { throw new KylinException(EMPTY_PARAMETER, "Table or database can not be null, please check again."); } + InternalTableService.validate(request); internalTableService.createInternalTable(project, table, database, request.getPartitionCols(), request.getDatePartitionFormat(), request.getTblProperties(), request.getStorageType()); return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, "", ""); @@ -150,6 +151,7 @@ public class InternalTableController extends NBasicController { if (table.isEmpty()) { throw new KylinException(INVALID_TABLE_NAME, MsgPicker.getMsg().getTableNameCannotEmpty()); } + InternalTableService.validate(request); internalTableService.updateInternalTable(project, table, database, request.getPartitionCols(), request.getDatePartitionFormat(), request.getTblProperties(), request.getStorageType()); return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, null, "");