From 3e1e524756df47dfaadde7dbf403cb12d563cff7 Mon Sep 17 00:00:00 2001 From: kangkaisen Date: Thu, 18 Aug 2016 19:17:37 +0800 Subject: [PATCH] KYLIN-1965 Check duplicated measure name --- .../cube/model/validation/rule/FunctionRule.java | 20 +++++++ .../model/validation/rule/FunctionRuleTest.java | 68 ++++++++++++++++++++++ webapp/app/js/controllers/cubeMeasures.js | 16 +++++ 3 files changed, 104 insertions(+) create mode 100644 core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/FunctionRule.java b/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/FunctionRule.java index 44b0be0..dcc715c 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/FunctionRule.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/model/validation/rule/FunctionRule.java @@ -62,6 +62,10 @@ public class FunctionRule implements IValidatorRule { public void validate(CubeDesc cube, ValidateContext context) { List measures = cube.getMeasures(); + if (validateMeasureNamesDuplicated(measures, context)) { + return; + } + List countFuncs = new ArrayList(); Iterator it = measures.iterator(); @@ -185,4 +189,20 @@ public class FunctionRule implements IValidatorRule { } } + + /** + * @param measures + */ + private boolean validateMeasureNamesDuplicated(List measures, ValidateContext context) { + Set nameSet = new HashSet<>(); + for (MeasureDesc measure: measures){ + if (nameSet.contains(measure.getName())){ + context.addResult(ResultLevel.ERROR, "There is duplicated measure's name: " + measure.getName()); + return true; + } else { + nameSet.add(measure.getName()); + } + } + return false; + } } diff --git a/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java b/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java new file mode 100644 index 0000000..48e01e3 --- /dev/null +++ b/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java @@ -0,0 +1,68 @@ +package org.apache.kylin.cube.model.validation.rule; + +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.util.JsonUtil; +import org.apache.kylin.common.util.LocalFileMetadataTestCase; +import org.apache.kylin.cube.model.CubeDesc; +import org.apache.kylin.cube.model.validation.ValidateContext; +import org.apache.kylin.metadata.MetadataManager; +import org.apache.kylin.metadata.model.MeasureDesc; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class FunctionRuleTest extends LocalFileMetadataTestCase { + private static KylinConfig config; + private static MetadataManager metadataManager; + + @Before + public void setUp() throws Exception { + this.createTestMetadata(); + config = KylinConfig.getInstanceFromEnv(); + metadataManager = MetadataManager.getInstance(config); + } + + @After + public void after() throws Exception { + this.cleanupTestMetadata(); + } + + @Test + public void testGoodDesc() throws IOException { + FunctionRule rule = new FunctionRule(); + + File f = new File(LocalFileMetadataTestCase.LOCALMETA_TEST_DATA + "/cube_desc/ssb.json"); + CubeDesc desc = JsonUtil.readValue(new FileInputStream(f), CubeDesc.class); + desc.init(config, metadataManager.getAllTablesMap()); + ValidateContext vContext = new ValidateContext(); + rule.validate(desc, vContext); + vContext.print(System.out); + assertTrue(vContext.getResults().length == 0); + } + + @Test + public void testValidateMeasureNamesDuplicated() throws IOException { + FunctionRule rule = new FunctionRule(); + + File f = new File(LocalFileMetadataTestCase.LOCALMETA_TEST_DATA + "/cube_desc/ssb.json"); + CubeDesc desc = JsonUtil.readValue(new FileInputStream(f), CubeDesc.class); + + MeasureDesc measureDescDuplicated = desc.getMeasures().get(1); + desc.getMeasures().add(measureDescDuplicated); + + desc.init(config, metadataManager.getAllTablesMap()); + ValidateContext vContext = new ValidateContext(); + rule.validate(desc, vContext); + + vContext.print(System.out); + assertTrue(vContext.getResults().length >= 1); + assertEquals("There is duplicated measure's name: " + measureDescDuplicated.getName(), vContext.getResults()[0].getMessage()); + } +} diff --git a/webapp/app/js/controllers/cubeMeasures.js b/webapp/app/js/controllers/cubeMeasures.js index 8db1356..9dec379 100644 --- a/webapp/app/js/controllers/cubeMeasures.js +++ b/webapp/app/js/controllers/cubeMeasures.js @@ -107,6 +107,12 @@ KylinApp.controller('CubeMeasuresCtrl', function ($scope, $modal,MetaModel,cubes SweetAlert.swal('', '[TOP_N] Group by Column is required', 'warning'); return false; } + + if ($scope.isNameDuplicated($scope.cubeMetaFrame.measures, $scope.newMeasure) == true) { + SweetAlert.swal('', 'The measure name: ' + $scope.newMeasure.name + ' is duplicated', 'warning'); + return false; + } + if($scope.nextPara.value!=="" && ($scope.newMeasure.function.expression == 'EXTENDED_COLUMN' || $scope.newMeasure.function.expression == 'TOP_N')){ $scope.newMeasure.function.parameter.next_parameter = jQuery.extend(true,{},$scope.nextPara); } @@ -117,12 +123,22 @@ KylinApp.controller('CubeMeasuresCtrl', function ($scope, $modal,MetaModel,cubes else { $scope.cubeMetaFrame.measures.push($scope.newMeasure); } + $scope.newMeasure = null; $scope.initUpdateMeasureStatus(); $scope.nextParameterInit(); return true; }; + $scope.isNameDuplicated = function (measures, newMeasure) { + var names = []; + for(var i = 0;i < measures.length; i++){ + names.push(measures[i].name); + } + var index = names.indexOf(newMeasure.name); + return index > -1; + } + $scope.nextParameterInit = function(){ $scope.nextPara = { "type":"column", -- 2.5.4 (Apple Git-61)