This is an automated email from the ASF dual-hosted git repository. xxyu pushed a commit to branch kylin5 in repository https://gitbox.apache.org/repos/asf/kylin.git
commit ae22f91de94d4e399f4498e51876e6ca9cd28712 Author: fanfanAlice <41991994+fanfanal...@users.noreply.github.com> AuthorDate: Sun Nov 20 11:44:47 2022 +0800 KYLIN-5395 sync column comment to dimension name and measure comment (#29499) * sync column comment to dimension name and measure comment * bug fix for special char replace Co-authored-by: fanfanAlice <18611532...@163.com> --- .../apache/kylin/metadata/model/ColumnDesc.java | 8 + .../org/apache/kylin/metadata/model/TblColRef.java | 4 +- .../rest/controller/open/OpenModelController.java | 17 ++ .../controller/open/OpenModelControllerTest.java | 16 ++ .../response/SynchronizedCommentsResponse.java | 220 +++++++++++++++++++++ .../apache/kylin/rest/service/ModelService.java | 8 +- .../kylin/rest/service/ModelServiceTest.java | 95 +++++++++ 7 files changed, 362 insertions(+), 6 deletions(-) diff --git a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java index a5968b6cf5..e179e2bb63 100644 --- a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java +++ b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java @@ -268,6 +268,14 @@ public class ColumnDesc implements Serializable { return desc; } + public String getCanonicalName() { + String tableName = null; + if (table != null) { + tableName = table.getIdentity(); + } + return tableName + "." + getName(); + } + @Override public int hashCode() { final int prime = 31; diff --git a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java index d4764ff2e2..13022d135d 100644 --- a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java +++ b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java @@ -203,7 +203,7 @@ public class TblColRef implements Serializable { this.table = table; this.column = column; } - + private String wrapIdentity(String wrap) { return wrap + getTableAlias() + wrap + "." + wrap + getName() + wrap; } @@ -281,7 +281,7 @@ public class TblColRef implements Serializable { } public String getCanonicalName() { - return getTable() + "." + getName(); + return column.getCanonicalName(); } public String getDatatype() { diff --git a/src/metadata-server/src/main/java/io/kyligence/kap/rest/controller/open/OpenModelController.java b/src/metadata-server/src/main/java/io/kyligence/kap/rest/controller/open/OpenModelController.java index d9642ade0c..23c16ef30a 100644 --- a/src/metadata-server/src/main/java/io/kyligence/kap/rest/controller/open/OpenModelController.java +++ b/src/metadata-server/src/main/java/io/kyligence/kap/rest/controller/open/OpenModelController.java @@ -68,6 +68,7 @@ import org.apache.kylin.rest.response.IndexResponse; import org.apache.kylin.rest.response.NModelDescResponse; import org.apache.kylin.rest.response.OpenGetIndexResponse; import org.apache.kylin.rest.response.OpenGetIndexResponse.IndexDetail; +import org.apache.kylin.rest.response.SynchronizedCommentsResponse; import org.apache.kylin.rest.service.FusionIndexService; import org.apache.kylin.rest.service.FusionModelService; import org.apache.kylin.rest.service.ModelService; @@ -111,6 +112,8 @@ public class OpenModelController extends NBasicController { .collect(Collectors.toSet()); public static final String MODEL_ID = "modelId"; + public static final String FACT_TABLE = "fact_table"; + @Autowired private NModelController modelController; @@ -493,4 +496,18 @@ public class OpenModelController extends NBasicController { throw new KylinException(FAILED_UPDATE_MODEL, root); } } + + @ApiOperation(value = "comments synchronization", tags = { "AI" }) + @PostMapping(value = "/comments_synchronization") + @ResponseBody + public EnvelopeResponse<SynchronizedCommentsResponse> commentsSynchronization( + @RequestBody ModelRequest modelRequest) { + modelRequest.setProject(checkProjectName(modelRequest.getProject())); + checkRequiredArg(ALIAS, modelRequest.getRawAlias()); + checkRequiredArg(FACT_TABLE, modelRequest.getRootFactTableName()); + SynchronizedCommentsResponse synchronizedCommentsResponse = new SynchronizedCommentsResponse(); + synchronizedCommentsResponse.syncComment(modelRequest); + modelService.checkBeforeModelSave(synchronizedCommentsResponse.getModelRequest()); + return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, synchronizedCommentsResponse, ""); + } } diff --git a/src/metadata-server/src/test/java/io/kyligence/kap/rest/controller/open/OpenModelControllerTest.java b/src/metadata-server/src/test/java/io/kyligence/kap/rest/controller/open/OpenModelControllerTest.java index e36ccf48de..ccc7864448 100644 --- a/src/metadata-server/src/test/java/io/kyligence/kap/rest/controller/open/OpenModelControllerTest.java +++ b/src/metadata-server/src/test/java/io/kyligence/kap/rest/controller/open/OpenModelControllerTest.java @@ -641,4 +641,20 @@ public class OpenModelControllerTest extends NLocalFileMetadataTestCase { .andExpect(MockMvcResultMatchers.status().isOk()); Mockito.verify(openModelController).updateSemantic(Mockito.any(OpenModelRequest.class)); } + + @Test + public void testCommentsSynchronization() throws Exception { + String project = "default"; + String modelName = "model1"; + ModelRequest modelRequest = new ModelRequest(); + modelRequest.setProject(project); + modelRequest.setAlias(modelName); + modelRequest.setRootFactTableName("test_fact_table"); + + mockMvc.perform(MockMvcRequestBuilders.post("/api/models/comments_synchronization") + .contentType(MediaType.APPLICATION_JSON).content(JsonUtil.writeValueAsString(modelRequest)) + .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON))) + .andExpect(MockMvcResultMatchers.status().isOk()); + Mockito.verify(openModelController).commentsSynchronization(modelRequest); + } } diff --git a/src/modeling-service/src/main/java/org/apache/kylin/rest/response/SynchronizedCommentsResponse.java b/src/modeling-service/src/main/java/org/apache/kylin/rest/response/SynchronizedCommentsResponse.java new file mode 100644 index 0000000000..3ec10cc795 --- /dev/null +++ b/src/modeling-service/src/main/java/org/apache/kylin/rest/response/SynchronizedCommentsResponse.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.kylin.rest.response; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.metadata.model.ColumnDesc; +import org.apache.kylin.metadata.model.FunctionDesc; +import org.apache.kylin.metadata.model.JoinTableDesc; +import org.apache.kylin.metadata.model.NDataModel; +import org.apache.kylin.metadata.model.NTableMetadataManager; +import org.apache.kylin.metadata.model.TableDesc; +import org.apache.kylin.rest.request.ModelRequest; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +public class SynchronizedCommentsResponse { + + @JsonProperty("model_request") + private ModelRequest modelRequest; + + @JsonProperty("conflict_info") + private ConflictInfo conflictInfo; + + @Data + @AllArgsConstructor + public static class ConflictInfo implements Serializable { + @JsonProperty("cols_with_same_comment") + private List<String> colsWithSameComment; + @JsonProperty("dims_origin_from_same_col") + private List<String> dimsOriginFromSameCol; + } + + public static final Pattern SPECIAL_CHAR_PTN = Pattern.compile("((?![\\u4E00-\\u9FA5a-zA-Z0-9 _\\-()%?()]+).)*"); + + public void syncComment(ModelRequest modelRequest) { + this.modelRequest = modelRequest; + Map<String, ColumnDesc> columnDescMap = getColumnDescMap(); + syncDimensionNames(columnDescMap, modelRequest.getSimplifiedDimensions()); + syncMeasureComments(columnDescMap, modelRequest.getSimplifiedMeasures()); + } + + private void syncDimensionNames(Map<String, ColumnDesc> columnDescMap, + List<NDataModel.NamedColumn> simplifiedDimensions) { + List<String> colsWithSameComment = Lists.newArrayList(); + List<String> dimsOriginFromSameCol = Lists.newArrayList(); + simplifiedDimensions.forEach(namedColumn -> { + String aliasDotColumn = StringUtils.upperCase(namedColumn.getAliasDotColumn()); + ColumnDesc columnDesc = columnDescMap.get(aliasDotColumn); + String name = StringUtils.upperCase(namedColumn.getColTableName()); + if (columnDesc == null) { + return; + } + String canonicalName = StringUtils.upperCase(columnDesc.getCanonicalName()); + List<ColumnDesc> columnDescList = simplifiedDimensions.stream() + .map(simpleDimension -> columnDescMap + .get(StringUtils.upperCase(simpleDimension.getAliasDotColumn()))) + .filter(Objects::nonNull) + .filter(column -> StringUtils.upperCase(column.getCanonicalName()).equals(canonicalName)) + .collect(Collectors.toList()); + long dimsOriginFromSameColCount = columnDescList.size(); + long colsWithSameCommentCount = simplifiedDimensions.stream() + .map(simpleDimension -> columnDescMap + .get(StringUtils.upperCase(simpleDimension.getAliasDotColumn()))) + .filter(Objects::nonNull) + .filter(column -> StringUtils.isNotBlank(column.getComment()) + && StringUtils.isNotBlank(columnDesc.getComment()) + && StringUtils.upperCase(column.getComment()) + .equals(StringUtils.upperCase(columnDesc.getComment()))) + .count(); + if (dimsOriginFromSameColCount > 1) { + dimsOriginFromSameCol.add(name); + } + if (colsWithSameCommentCount > 1) { + colsWithSameComment.add(name); + } + if (dimsOriginFromSameColCount == 1 && colsWithSameCommentCount == 1 + && StringUtils.isNotBlank(columnDesc.getComment())) { + name = columnDesc.getComment(); + } + namedColumn.setName(name); + }); + this.modelRequest.setSimplifiedDimensions(simplifiedDimensions); + this.conflictInfo = new ConflictInfo(colsWithSameComment, dimsOriginFromSameCol); + } + + private void syncMeasureComments(Map<String, ColumnDesc> columnDescMap, + List<SimplifiedMeasure> simplifiedMeasures) { + simplifiedMeasures.forEach(simplifiedMeasure -> { + List<ParameterResponse> parameterResponses = simplifiedMeasure.getParameterValue().stream().filter( + parameterResponse -> !FunctionDesc.PARAMETER_TYPE_CONSTANT.equals(parameterResponse.getType())) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(parameterResponses)) { + return; + } + String aliasDotColumn = parameterResponses.get(0).getValue(); + ColumnDesc columnDesc = columnDescMap.get(aliasDotColumn); + if (columnDesc != null && StringUtils.isNotBlank(columnDesc.getComment())) { + simplifiedMeasure.setComment(columnDesc.getComment()); + } + }); + modelRequest.setSimplifiedMeasures(simplifiedMeasures); + } + + public Map<String, ColumnDesc> getColumnDescMap() { + Map<String, ColumnDesc> columnDescMap = Maps.newHashMap(); + String project = modelRequest.getProject(); + String factTableName = modelRequest.getRootFactTableName(); + Set<String> computedColumnNames = modelRequest.getComputedColumnNames().stream().map(StringUtils::upperCase) + .collect(Collectors.toSet()); + List<JoinTableDesc> joinTables = modelRequest.getJoinTables(); + List<NDataModel.NamedColumn> simplifiedDimensions = modelRequest.getSimplifiedDimensions(); + simplifiedDimensions.forEach(namedColumn -> putColumnDesc(project, computedColumnNames, factTableName, + joinTables, columnDescMap, namedColumn.getAliasDotColumn())); + List<SimplifiedMeasure> simplifiedMeasures = modelRequest.getSimplifiedMeasures(); + simplifiedMeasures.forEach(simplifiedMeasure -> { + List<ParameterResponse> parameterResponses = simplifiedMeasure.getParameterValue().stream().filter( + parameterResponse -> !FunctionDesc.PARAMETER_TYPE_CONSTANT.equals(parameterResponse.getType())) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(parameterResponses)) { + return; + } + parameterResponses.forEach(parameterResponse -> putColumnDesc(project, computedColumnNames, factTableName, + joinTables, columnDescMap, parameterResponse.getValue())); + }); + return columnDescMap; + } + + private void putColumnDesc(String project, Set<String> computedColumnNames, String factTableName, + List<JoinTableDesc> joinTables, Map<String, ColumnDesc> columnDescMap, String aliasDotColumn) { + if (aliasDotColumn == null) { + return; + } + ColumnDesc columnDesc = getColumnDescByAliasDotColumn(project, StringUtils.upperCase(aliasDotColumn), + computedColumnNames, StringUtils.upperCase(factTableName), joinTables); + if (columnDesc != null) { + columnDescMap.put(aliasDotColumn, columnDesc); + } + } + + private ColumnDesc getColumnDescByAliasDotColumn(String project, String aliasDotColumn, + Set<String> computedColumnNames, String factTableName, List<JoinTableDesc> joinTables) { + String[] aliasDotColumnSplit = aliasDotColumn.split("\\."); + if (aliasDotColumnSplit.length != 2) { + return null; + } + String tableName = aliasDotColumnSplit[0]; + String columnName = aliasDotColumnSplit[1]; + if (computedColumnNames.contains(aliasDotColumn) || computedColumnNames.contains(columnName)) { + return null; + } + String factTableAlias = factTableName; + if (factTableName.contains(".") && factTableName.split("\\.").length == 2) { + factTableAlias = factTableName.split("\\.")[1]; + } + NTableMetadataManager mgr = NTableMetadataManager.getInstance(KylinConfig.getInstanceFromEnv(), project); + TableDesc tableDesc; + if (tableName.equals(factTableAlias)) { + tableDesc = mgr.getTableDesc(factTableName); + } else { + Optional<JoinTableDesc> joinTable = joinTables.stream() + .filter(joinTableDesc -> StringUtils.upperCase(joinTableDesc.getAlias()).equals(tableName)) + .findFirst(); + if (joinTable.isPresent()) { + tableDesc = mgr.getTableDesc(joinTable.get().getTable()); + } else { + return null; + } + } + Optional<ColumnDesc> column = Arrays.stream(tableDesc.getColumns()) + .filter(columnDesc -> StringUtils.upperCase(columnDesc.getName()).equals(columnName)).findFirst(); + if (column.isPresent()) { + ColumnDesc columnDesc = column.get(); + String comment = columnDesc.getComment(); + if (comment != null) { + columnDesc.setComment(replaceInvalidCharacters(comment.trim())); + } + return columnDesc; + } + return null; + } + + private String replaceInvalidCharacters(String name) { + Matcher matcher = SPECIAL_CHAR_PTN.matcher(name); + return matcher.replaceAll(""); + } +} diff --git a/src/modeling-service/src/main/java/org/apache/kylin/rest/service/ModelService.java b/src/modeling-service/src/main/java/org/apache/kylin/rest/service/ModelService.java index ab859e89b0..77fd3c6c5f 100644 --- a/src/modeling-service/src/main/java/org/apache/kylin/rest/service/ModelService.java +++ b/src/modeling-service/src/main/java/org/apache/kylin/rest/service/ModelService.java @@ -298,9 +298,9 @@ public class ModelService extends AbstractModelService implements TableModelSupp private static final String LAST_MODIFY = "last_modify"; public static final String REC_COUNT = "recommendations_count"; - public static final String VALID_NAME_FOR_DIMENSION = "^[\\u4E00-\\u9FA5a-zA-Z0-9 _\\-()%?()]+$"; + public static final Pattern VALID_NAME_FOR_DIMENSION = Pattern.compile("^[\\u4E00-\\u9FA5a-zA-Z0-9 _\\-()%?()]+$"); - public static final String VALID_NAME_FOR_MEASURE = "^[\\u4E00-\\u9FA5a-zA-Z0-9 _\\-()%?().]+$"; + public static final Pattern VALID_NAME_FOR_MEASURE = Pattern.compile("^[\\u4E00-\\u9FA5a-zA-Z0-9 _\\-()%?().]+$"); private static final List<String> MODEL_CONFIG_BLOCK_LIST = Lists.newArrayList("kylin.index.rule-scheduler-data"); @@ -2149,7 +2149,7 @@ public class ModelService extends AbstractModelService implements TableModelSupp dimension.setName(StringUtils.trim(dimension.getName())); // check if the dimension name is valid if (StringUtils.length(dimension.getName()) > maxModelDimensionMeasureNameLength - || !Pattern.compile(VALID_NAME_FOR_DIMENSION).matcher(dimension.getName()).matches()) + || !VALID_NAME_FOR_DIMENSION.matcher(dimension.getName()).matches()) throw new KylinException(INVALID_NAME, String.format(Locale.ROOT, MsgPicker.getMsg().getInvalidDimensionName(), dimension.getName(), maxModelDimensionMeasureNameLength)); @@ -2216,7 +2216,7 @@ public class ModelService extends AbstractModelService implements TableModelSupp if (!KylinConfig.getInstanceFromEnv().isMeasureNameCheckEnabled()) { return true; } - return Pattern.compile(VALID_NAME_FOR_MEASURE).matcher(measureName).matches(); + return VALID_NAME_FOR_MEASURE.matcher(measureName).matches(); } private boolean isDupMeasure(SimplifiedMeasure measure, SimplifiedMeasure measure1) { diff --git a/src/modeling-service/src/test/java/org/apache/kylin/rest/service/ModelServiceTest.java b/src/modeling-service/src/test/java/org/apache/kylin/rest/service/ModelServiceTest.java index e55b82cdfe..e8edf45716 100644 --- a/src/modeling-service/src/test/java/org/apache/kylin/rest/service/ModelServiceTest.java +++ b/src/modeling-service/src/test/java/org/apache/kylin/rest/service/ModelServiceTest.java @@ -71,6 +71,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.TimeZone; import java.util.TreeMap; @@ -148,6 +149,7 @@ import org.apache.kylin.metadata.model.SegmentStatusEnum; import org.apache.kylin.metadata.model.SegmentStatusEnumToDisplay; import org.apache.kylin.metadata.model.Segments; import org.apache.kylin.metadata.model.TableDesc; +import org.apache.kylin.metadata.model.TableRef; import org.apache.kylin.metadata.model.TblColRef; import org.apache.kylin.metadata.model.VolatileRange; import org.apache.kylin.metadata.model.util.ExpandableMeasureUtil; @@ -185,6 +187,7 @@ import org.apache.kylin.rest.response.SegmentPartitionResponse; import org.apache.kylin.rest.response.SimplifiedColumnResponse; import org.apache.kylin.rest.response.SimplifiedMeasure; import org.apache.kylin.rest.response.SimplifiedTableResponse; +import org.apache.kylin.rest.response.SynchronizedCommentsResponse; import org.apache.kylin.rest.util.AclEvaluate; import org.apache.kylin.rest.util.AclPermissionUtil; import org.apache.kylin.rest.util.AclUtil; @@ -5588,4 +5591,96 @@ public class ModelServiceTest extends SourceTestCase { measure.setParameterValue(Lists.newArrayList(parameterResponse)); return measure; } + + @Test + public void testCreateModelSyncDimensionOrMeasure() { + NDataModelManager modelManager = NDataModelManager.getInstance(KylinConfig.getInstanceFromEnv(), "default"); + ModelRequest modelRequest = createModelRequest(modelManager); + SynchronizedCommentsResponse response = new SynchronizedCommentsResponse(); + response.syncComment(modelRequest); + ModelRequest newModelRequest = response.getModelRequest(); + long measureCount = newModelRequest.getSimplifiedMeasures().stream() + .filter(simplifiedMeasure -> simplifiedMeasure.getComment() != null + && simplifiedMeasure.getComment().contains("____")) + .count(); + long dimensionCount = newModelRequest.getSimplifiedDimensions().stream() + .filter(namedColumn -> namedColumn.getName().contains("____")).count(); + Assert.assertEquals(11, measureCount); + Assert.assertEquals(10, dimensionCount); + SynchronizedCommentsResponse.ConflictInfo conflictInfo = response.getConflictInfo(); + Assert.assertEquals(2, conflictInfo.getColsWithSameComment().size()); + Assert.assertEquals(20, conflictInfo.getDimsOriginFromSameCol().size()); + } + + private ModelRequest createModelRequest(NDataModelManager modelManager) { + NDataModel model = modelManager.getDataModelDesc("82fa7671-a935-45f5-8779-85703601f49a"); + ModelRequest modelRequest = new ModelRequest(model); + modelRequest.setProject("default"); + modelRequest.setAlias("test_model"); + modelRequest.setRootFactTableName(model.getRootFactTableName()); + modelRequest.setLastModified(0L); + modelRequest.setStart("0"); + modelRequest.setEnd("100"); + modelRequest.setUuid(null); + + List<NamedColumn> oriAllNamedColumns = model.getAllNamedColumns(); + + List<SimplifiedMeasure> simplified_measures = model.getAllMeasures().stream().map(oldSimplifiedMeasure -> { + SimplifiedMeasure simplifiedMeasure = new SimplifiedMeasure(); + simplifiedMeasure.setName(oldSimplifiedMeasure.getName()); + simplifiedMeasure.setExpression(oldSimplifiedMeasure.getFunction().getExpression()); + simplifiedMeasure.setReturnType(oldSimplifiedMeasure.getFunction().getReturnType()); + List<ParameterResponse> parameterResponses = oldSimplifiedMeasure.getFunction().getParameters().stream() + .map(parameterDesc -> { + String value = parameterDesc.getValue(); + String type = parameterDesc.getType(); + ParameterResponse response = new ParameterResponse(); + response.setType(type); + response.setValue(value); + return response; + }).collect(Collectors.toList()); + simplifiedMeasure.setParameterValue(parameterResponses); + return simplifiedMeasure; + }).collect(Collectors.toList()); + + modelRequest.setSimplifiedMeasures(simplified_measures); + modelRequest.setSimplifiedDimensions(oriAllNamedColumns); + + NTableMetadataManager tableMetadataManager = NTableMetadataManager.getInstance(KylinConfig.getInstanceFromEnv(), + "default"); + TableDesc tableDesc = tableMetadataManager.getTableDesc("DEFAULT.TEST_KYLIN_FACT"); + int length = tableDesc.getColumns().length; + ColumnDesc[] columns = new ColumnDesc[length]; + for (int i = 0; i < length; i++) { + ColumnDesc column = tableDesc.getColumns()[i]; + column.setComment( + column.getComment() == null ? column.getName() + "____" + i : column.getComment() + "____" + i); + columns[i] = column; + } + String comment = columns[2].getComment(); + columns[3].setComment(comment); + tableDesc.setColumns(columns); + tableMetadataManager.updateTableDesc(tableDesc); + return modelRequest; + } + + @Test + public void testGetCanonicalName() { + TblColRef colRef = TblColRef.newDynamicColumn("test"); + Assert.assertEquals("NULL.TEST", colRef.getCanonicalName()); + TblColRef innerColumn = TblColRef.newInnerColumn("test", TblColRef.InnerDataTypeEnum.AGGREGATION_TYPE); + Assert.assertEquals("DEFAULT._KYLIN_TABLE.TEST", innerColumn.getCanonicalName()); + NDataModelManager modelManager = NDataModelManager.getInstance(KylinConfig.getInstanceFromEnv(), "default"); + NDataModel model = modelManager.getDataModelDesc("82fa7671-a935-45f5-8779-85703601f49a"); + List<JoinTableDesc> joinTables = model.getJoinTables(); + if (joinTables.size() == 0) { + return; + } + TableRef tableRef = joinTables.get(0).getTableRef(); + Optional<TblColRef> first = tableRef.getColumns().stream().findFirst(); + if (first.isPresent()) { + TblColRef colRef1 = first.get(); + Assert.assertEquals("DEFAULT.TEST_ORDER.ORDER_ID", colRef1.getCanonicalName()); + } + } }