You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by sh...@apache.org on 2015/09/02 03:53:26 UTC
incubator-kylin git commit: KYLIN-958 disallow changing data model in
the backend
Repository: incubator-kylin
Updated Branches:
refs/heads/0.7-staging 6ba5b51f2 -> dbbbc1e55
KYLIN-958 disallow changing data model in the backend
Signed-off-by: shaofengshi <sh...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kylin/commit/dbbbc1e5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kylin/tree/dbbbc1e5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kylin/diff/dbbbc1e5
Branch: refs/heads/0.7-staging
Commit: dbbbc1e5541ee6f2cce272ec48c518624bc5392f
Parents: 6ba5b51
Author: gaodayue <ga...@meituan.com>
Authored: Thu Aug 27 14:00:25 2015 +0800
Committer: shaofengshi <sh...@apache.org>
Committed: Wed Sep 2 09:51:54 2015 +0800
----------------------------------------------------------------------
.../common/persistence/HBaseResourceStore.java | 2 +-
.../org/apache/kylin/cube/CubeDescManager.java | 14 +-
.../kylin/metadata/model/DataModelDesc.java | 41 +++++
.../kylin/rest/controller/CubeController.java | 76 +++++----
.../apache/kylin/rest/service/CubeService.java | 9 +-
.../rest/controller/CubeControllerTest.java | 171 ++++++++++++++-----
6 files changed, 228 insertions(+), 85 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/dbbbc1e5/common/src/main/java/org/apache/kylin/common/persistence/HBaseResourceStore.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/persistence/HBaseResourceStore.java b/common/src/main/java/org/apache/kylin/common/persistence/HBaseResourceStore.java
index 37b8f8d..1c4a7ba 100644
--- a/common/src/main/java/org/apache/kylin/common/persistence/HBaseResourceStore.java
+++ b/common/src/main/java/org/apache/kylin/common/persistence/HBaseResourceStore.java
@@ -237,7 +237,7 @@ public class HBaseResourceStore extends ResourceStore {
boolean ok = table.checkAndPut(row, B_FAMILY, B_COLUMN_TS, bOldTS, put);
if (!ok) {
long real = getResourceTimestamp(resPath);
- throw new IllegalStateException("Overwriting conflict " + resPath + ", expect old TS " + oldTS + ", but it is " + real);
+ throw new IllegalStateException("Overwriting conflict " + resPath + ", expect old TS " + real + ", but it is " + oldTS);
}
table.flushCommits();
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/dbbbc1e5/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java b/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
index cd270cf..dfb1b88 100644
--- a/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
+++ b/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
@@ -22,7 +22,7 @@ import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.kylin.common.KylinConfig;
import org.apache.kylin.common.persistence.JsonSerializer;
import org.apache.kylin.common.persistence.ResourceStore;
@@ -253,6 +253,14 @@ public class CubeDescManager {
desc.setSignature(desc.calculateSignature());
+ // drop cube segments if signature changes
+ CubeInstance cube = getCubeManager().getCube(desc.getName());
+ if (cube != null && !StringUtils.equals(desc.getSignature(), cube.getDescriptor().getSignature())) {
+ logger.info("Detect signature change of [" + desc.getName() + "], drop all existing segments");
+ cube.getSegments().clear();
+ getCubeManager().updateCube(cube);
+ }
+
// Save Source
String path = desc.getResourcePath();
getStore().putResource(path, desc, CUBE_DESC_SERIALIZER);
@@ -269,6 +277,10 @@ public class CubeDescManager {
return MetadataManager.getInstance(config);
}
+ private CubeManager getCubeManager() {
+ return CubeManager.getInstance(config);
+ }
+
private ResourceStore getStore() {
return ResourceStore.getStore(this.config);
}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/dbbbc1e5/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
index a37d4c6..cb1e784 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
@@ -18,14 +18,17 @@
package org.apache.kylin.metadata.model;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.kylin.common.persistence.ResourceStore;
import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.common.util.JsonUtil;
import org.apache.kylin.common.util.StringUtil;
import org.apache.kylin.metadata.MetadataConstants;
@@ -33,9 +36,12 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Sets;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class DataModelDesc extends RootPersistentEntity {
+ private static final Logger logger = LoggerFactory.getLogger(DataModelDesc.class);
public static enum RealizationCapacity {
SMALL, MEDIUM, LARGE
@@ -213,6 +219,41 @@ public class DataModelDesc extends RootPersistentEntity {
}
}
+ /**
+ * Check whether two data model are compatible or not. Compatible means
+ * having the same structure. Tow models could be compatible even they
+ * have different UUID or last modified time.
+ * @param that model to compare with
+ * @return true if compatible, false otherwise.
+ */
+ public boolean compatibleWith(DataModelDesc that) {
+ if (this == that)
+ return true;
+
+ if (that == null)
+ return false;
+
+ try {
+ String thisRepr = excludeHeaderInfo(this);
+ String thatRepr = excludeHeaderInfo(that);
+ return StringUtils.equals(thisRepr, thatRepr);
+
+ } catch (IOException e) {
+ logger.error("Failed to serialize DataModelDesc to string", e);
+ return false;
+ }
+ }
+
+ private String excludeHeaderInfo(DataModelDesc modelDesc) throws IOException {
+ // make a copy
+ String repr = JsonUtil.writeValueAsString(modelDesc);
+ DataModelDesc copy = JsonUtil.readValue(repr, DataModelDesc.class);
+
+ copy.setUuid(null);
+ copy.setLastModified(0);
+ return JsonUtil.writeValueAsString(copy);
+ }
+
@Override
public String toString() {
return "DataModelDesc [name=" + name + "]";
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/dbbbc1e5/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index 9f29753..734ef32 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -330,56 +330,57 @@ public class CubeController extends BasicController {
}
/**
- * Get available table list of the input database
+ * Update cube description. If cube signature has changed, all existing cube segments are dropped.
*
* @return Table metadata array
* @throws JsonProcessingException
- * @throws IOException
*/
@RequestMapping(value = "", method = { RequestMethod.PUT })
@ResponseBody
public CubeRequest updateCubeDesc(@RequestBody CubeRequest cubeRequest) throws JsonProcessingException {
-
- //Update Model
- MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
- DataModelDesc modelDesc = deserializeDataModelDesc(cubeRequest);
- if (modelDesc == null) {
+ CubeDesc desc = deserializeCubeDesc(cubeRequest);
+ if (desc == null) {
return cubeRequest;
}
- try {
- DataModelDesc existingModel = metaManager.getDataModelDesc(modelDesc.getName());
- if (existingModel == null) {
- metaManager.createDataModelDesc(modelDesc);
- } else {
+ final String cubeName = desc.getName();
+ if (StringUtils.isEmpty(cubeName)) {
+ return errorRequest(cubeRequest, "Missing cubeName");
+ }
- //ignore overwriting conflict checking before splict MODEL & CUBE
- modelDesc.setLastModified(existingModel.getLastModified());
- metaManager.updateDataModelDesc(modelDesc);
+ MetadataManager metadataManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+ // KYLIN-958: disallow data model change
+ if (StringUtils.isNotEmpty(cubeRequest.getModelDescData())) {
+ DataModelDesc modelDesc = deserializeDataModelDesc(cubeRequest);
+ if (modelDesc == null) {
+ return cubeRequest;
}
- } catch (IOException e) {
- // TODO Auto-generated catch block
- logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
- throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
- }
+ final String modeName = modelDesc.getName();
- //update cube
- CubeDesc desc = deserializeCubeDesc(cubeRequest);
+ if (!StringUtils.equals(desc.getModelName(), modeName)) {
+ return errorRequest(cubeRequest, "CubeDesc.model_name " + desc.getModelName() + " not consistent with model " + modeName);
+ }
+
+ DataModelDesc oldModelDesc = metadataManager.getDataModelDesc(modeName);
+ if (oldModelDesc == null) {
+ return errorRequest(cubeRequest, "Data model " + modeName + " not found");
+ }
+
+ if (!modelDesc.compatibleWith(oldModelDesc)) {
+ return errorRequest(cubeRequest, "Update data model is not allowed! Please create a new cube if needed");
+ }
- if (desc == null) {
- return cubeRequest;
}
// Check if the cube is editable
if (!cubeService.isCubeDescEditable(desc)) {
String error = "Cube desc " + desc.getName().toUpperCase() + " is not editable.";
- updateRequest(cubeRequest, false, error);
- return cubeRequest;
+ return errorRequest(cubeRequest, error);
}
try {
- CubeInstance cube = cubeService.getCubeManager().getCube(cubeRequest.getCubeName());
+ CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
cube.setRetentionRange(desc.getRetentionRange());
String projectName = (null == cubeRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject();
desc = cubeService.updateCubeAndDesc(cube, desc, projectName);
@@ -395,7 +396,7 @@ public class CubeController extends BasicController {
cubeRequest.setSuccessful(true);
} else {
logger.warn("Cube " + desc.getName() + " fail to create because " + desc.getError());
- updateRequest(cubeRequest, false, omitMessage(desc.getError()));
+ errorRequest(cubeRequest, omitMessage(desc.getError()));
}
String descData = JsonUtil.writeValueAsIndentString(desc);
cubeRequest.setCubeDescData(descData);
@@ -449,15 +450,15 @@ public class CubeController extends BasicController {
private CubeDesc deserializeCubeDesc(CubeRequest cubeRequest) {
CubeDesc desc = null;
try {
- logger.debug("Saving cube " + cubeRequest.getCubeDescData());
+ logger.debug("Deserialize cube desc " + cubeRequest.getCubeDescData());
desc = JsonUtil.readValue(cubeRequest.getCubeDescData(), CubeDesc.class);
// desc.setRetentionRange(cubeRequest.getRetentionRange());
} catch (JsonParseException e) {
logger.error("The cube definition is not valid.", e);
- updateRequest(cubeRequest, false, e.getMessage());
+ errorRequest(cubeRequest, e.getMessage());
} catch (JsonMappingException e) {
logger.error("The cube definition is not valid.", e);
- updateRequest(cubeRequest, false, e.getMessage());
+ errorRequest(cubeRequest, e.getMessage());
} catch (IOException e) {
logger.error("Failed to deal with the request.", e);
throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
@@ -468,14 +469,14 @@ public class CubeController extends BasicController {
private DataModelDesc deserializeDataModelDesc(CubeRequest cubeRequest) {
DataModelDesc desc = null;
try {
- logger.debug("Saving MODEL " + cubeRequest.getModelDescData());
+ logger.debug("Deserialize data model " + cubeRequest.getModelDescData());
desc = JsonUtil.readValue(cubeRequest.getModelDescData(), DataModelDesc.class);
} catch (JsonParseException e) {
logger.error("The data model definition is not valid.", e);
- updateRequest(cubeRequest, false, e.getMessage());
+ errorRequest(cubeRequest, e.getMessage());
} catch (JsonMappingException e) {
logger.error("The data model definition is not valid.", e);
- updateRequest(cubeRequest, false, e.getMessage());
+ errorRequest(cubeRequest, e.getMessage());
} catch (IOException e) {
logger.error("Failed to deal with the request.", e);
throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
@@ -496,10 +497,11 @@ public class CubeController extends BasicController {
return buffer.toString();
}
- private void updateRequest(CubeRequest request, boolean success, String message) {
+ private CubeRequest errorRequest(CubeRequest request, String errmsg) {
request.setCubeDescData("");
- request.setSuccessful(success);
- request.setMessage(message);
+ request.setSuccessful(false);
+ request.setMessage(errmsg);
+ return request;
}
public void setCubeService(CubeService cubeService) {
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/dbbbc1e5/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
index 21c6ec7..be356af 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -236,11 +236,11 @@ public class CubeService extends BasicService {
}
try {
- if (!cube.getDescriptor().calculateSignature().equals(cube.getDescriptor().getSignature())) {
- this.releaseAllSegments(cube);
+ CubeDesc updatedCubeDesc = getCubeDescManager().updateCubeDesc(desc);
+ if (!updatedCubeDesc.getError().isEmpty()) {
+ return updatedCubeDesc;
}
- CubeDesc updatedCubeDesc = getCubeDescManager().updateCubeDesc(desc);
cube = getCubeManager().updateCube(cube);
int cuboidCount = CuboidCLI.simulateCuboidGeneration(updatedCubeDesc);
@@ -388,9 +388,6 @@ public class CubeService extends BasicService {
if (!cubingJobs.isEmpty()) {
throw new JobException("Enable is not allowed with a running job.");
}
- if (!cube.getDescriptor().calculateSignature().equals(cube.getDescriptor().getSignature())) {
- this.releaseAllSegments(cube);
- }
cube.setStatus(RealizationStatusEnum.READY);
try {
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/dbbbc1e5/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
index cf1a718..2f12851 100644
--- a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
@@ -19,32 +19,34 @@
package org.apache.kylin.rest.controller;
import java.io.IOException;
-import java.io.StringWriter;
import java.util.List;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.kylin.common.util.JsonUtil;
import org.apache.kylin.cube.CubeInstance;
import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.RowKeyColDesc;
import org.apache.kylin.metadata.model.DataModelDesc;
import org.apache.kylin.rest.request.CubeRequest;
import org.apache.kylin.rest.service.CubeService;
import org.apache.kylin.rest.service.JobService;
import org.apache.kylin.rest.service.ServiceTestBase;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
/**
* @author xduo
*/
public class CubeControllerTest extends ServiceTestBase {
+ private static final String SRC_CUBE_NAME = "test_kylin_cube_with_slr_ready";
+ private static final String TEST_CUBE_NAME = SRC_CUBE_NAME + "_test_save";
private CubeController cubeController;
private CubeDescController cubeDescController;
private ModelController modelController;
+ private CubeDesc srcCubeDesc;
@Autowired
CubeService cubeService;
@@ -52,29 +54,39 @@ public class CubeControllerTest extends ServiceTestBase {
JobService jobService;
@Before
- public void setup() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
-
cubeController = new CubeController();
cubeController.setCubeService(cubeService);
cubeController.setJobService(jobService);
+
cubeDescController = new CubeDescController();
cubeDescController.setCubeService(cubeService);
modelController = new ModelController();
modelController.setCubeService(cubeService);
+
+ srcCubeDesc = getCubeDescByName(SRC_CUBE_NAME);
+
+ saveTestCube(TEST_CUBE_NAME);
}
- @Test
- public void testBasics() throws IOException {
- CubeDesc[] cubes = (CubeDesc[]) cubeDescController.getCube("test_kylin_cube_with_slr_ready");
- Assert.assertNotNull(cubes);
- Assert.assertNotNull(cubeController.getSql("test_kylin_cube_with_slr_ready", "20130331080000_20131212080000"));
- Assert.assertNotNull(cubeController.getCubes(null, null, 0, 5));
+ @After
+ public void tearDown() throws Exception {
+ cubeController.deleteCube(TEST_CUBE_NAME);
+ super.after();
+ }
+
+ private CubeDesc getCubeDescByName(String cubeDescName) {
+ CubeDesc[] cubes = cubeDescController.getCube(cubeDescName);
+ if (cubes == null || cubes.length < 1) {
+ throw new IllegalStateException("cube desc " + cubeDescName + " not existed");
+ }
+ return cubes[0];
+ }
- CubeDesc cube = cubes[0];
+ private void saveTestCube(final String newCubeName) throws IOException {
CubeDesc newCube = new CubeDesc();
- String newCubeName = cube.getName() + "_test_save";
try {
cubeController.deleteCube(newCubeName);
@@ -83,45 +95,124 @@ public class CubeControllerTest extends ServiceTestBase {
}
newCube.setName(newCubeName);
- newCube.setModelName(cube.getModelName());
- newCube.setModel(cube.getModel());
- newCube.setDimensions(cube.getDimensions());
- newCube.setHBaseMapping(cube.getHBaseMapping());
- newCube.setMeasures(cube.getMeasures());
- newCube.setConfig(cube.getConfig());
- newCube.setRowkey(cube.getRowkey());
-
- String newModelName = newCubeName + "_model_desc";
- newCube.getModel().setName(newModelName);//generate a random model
+ newCube.setModelName(newCubeName);
+ newCube.setModel(srcCubeDesc.getModel());
+ newCube.setDimensions(srcCubeDesc.getDimensions());
+ newCube.setHBaseMapping(srcCubeDesc.getHBaseMapping());
+ newCube.setMeasures(srcCubeDesc.getMeasures());
+ newCube.setConfig(srcCubeDesc.getConfig());
+ newCube.setRowkey(srcCubeDesc.getRowkey());
+
+ newCube.getModel().setName(newCubeName);
newCube.getModel().setLastModified(0);
- ObjectMapper cubeDescMapper = new ObjectMapper();
- StringWriter cubeDescWriter = new StringWriter();
- cubeDescMapper.writeValue(cubeDescWriter, newCube);
+ CubeRequest cubeRequest = new CubeRequest();
+ cubeRequest.setCubeDescData(JsonUtil.writeValueAsIndentString(newCube));
+ cubeRequest.setModelDescData(JsonUtil.writeValueAsIndentString(newCube.getModel()));
- ObjectMapper modelDescMapper = new ObjectMapper();
- StringWriter modelDescWriter = new StringWriter();
- modelDescMapper.writeValue(modelDescWriter, newCube.getModel());
+ CubeRequest result = cubeController.saveCubeDesc(cubeRequest);
+ Assert.assertTrue(result.getSuccessful());
+ }
- CubeRequest cubeRequest = new CubeRequest();
- cubeRequest.setCubeDescData(cubeDescWriter.toString());
- cubeRequest.setModelDescData(modelDescWriter.toString());
- cubeRequest = cubeController.saveCubeDesc(cubeRequest);
+ @Test
+ public void testBasics() throws IOException {
+
+ Assert.assertNotNull(cubeController.getSql(SRC_CUBE_NAME, "20130331080000_20131212080000"));
+ Assert.assertNotNull(cubeController.getCubes(null, null, 0, 5));
- DataModelDesc model = modelController.getModel(newModelName);
+ DataModelDesc model = modelController.getModel(TEST_CUBE_NAME);
Assert.assertNotNull(model);
List<String> notifyList = Lists.newArrayList();
notifyList.add("john@example.com");
- cubeController.updateNotifyList(newCubeName, notifyList);
- cubeController.updateCubeCost(newCubeName, 80);
+ cubeController.updateNotifyList(TEST_CUBE_NAME, notifyList);
+ cubeController.updateCubeCost(TEST_CUBE_NAME, 80);
- List<CubeInstance> cubeInstances = cubeController.getCubes(newCubeName, "default", 1, 0);
+ List<CubeInstance> cubeInstances = cubeController.getCubes(TEST_CUBE_NAME, "default", 1, 0);
CubeInstance cubeInstance = cubeInstances.get(0);
Assert.assertTrue(cubeInstance.getDescriptor().getNotifyList().contains("john@example.com"));
Assert.assertTrue(cubeInstance.getCost() == 80);
- cubeController.deleteCube(newCubeName);
}
+ @Test
+ public void testUpdateCubeDesc() throws IOException {
+ CubeDesc newCubeDesc = getCubeDescByName(TEST_CUBE_NAME);
+
+ // -------------------------------------------------------
+ // negative case
+ // -------------------------------------------------------
+
+ // invalid cube desc
+ CubeRequest req = new CubeRequest();
+ req.setCubeDescData("invalid");
+ assertUpdateFail(req);
+
+ // invalid data model
+ req = new CubeRequest();
+ req.setCubeDescData(JsonUtil.writeValueAsIndentString(newCubeDesc));
+ req.setModelDescData("invalid");
+ assertUpdateFail(req);
+
+ // data model's model_name not consistent with model name
+ req = new CubeRequest();
+ req.setCubeDescData("{\"name\" : \"myCube\", \"model_name\" : \"anotherModelName\"}");
+ req.setModelDescData("{\"name\" : \"myCube\"}");
+ assertUpdateFail(req);
+
+ // non-existed data model
+ req = new CubeRequest();
+ req.setCubeDescData("{\"name\" : \"noSuchCube\", \"model_name\" : \"noSuchModel\"}");
+ req.setModelDescData("{\"name\" : \"noSuchModel\"}");
+ assertUpdateFail(req);
+
+ // modified data model
+ req = new CubeRequest();
+ req.setCubeDescData(JsonUtil.writeValueAsIndentString(newCubeDesc));
+
+ DataModelDesc modifiedModel = new DataModelDesc();
+ modifiedModel.setName(TEST_CUBE_NAME);
+ modifiedModel.setFactTable("anotherFactTable");
+ req.setModelDescData(JsonUtil.writeValueAsIndentString(modifiedModel));
+
+ assertUpdateFail(req);
+
+ // -------------------------------------------------------
+ // positive case
+ // -------------------------------------------------------
+ req = new CubeRequest();
+ req.setModelDescData(JsonUtil.writeValueAsIndentString(newCubeDesc.getModel()));
+
+ // no signature change
+ newCubeDesc.setDescription("hello cube");
+ req.setCubeDescData(JsonUtil.writeValueAsIndentString(newCubeDesc));
+ CubeRequest res = cubeController.updateCubeDesc(req);
+ Assert.assertTrue(res.getSuccessful());
+
+ CubeDesc resultDesc = getCubeDescByName(TEST_CUBE_NAME);
+ Assert.assertEquals("hello cube", resultDesc.getDescription());
+ Assert.assertEquals(newCubeDesc.getSignature(), resultDesc.getSignature());
+
+ // signature change (reverse row key column order)
+ newCubeDesc = getCubeDescByName(TEST_CUBE_NAME);
+ RowKeyColDesc[] rowkeyColumns = newCubeDesc.getRowkey().getRowKeyColumns();
+ for (int i = 0, j = rowkeyColumns.length - 1; i < j; i++, j--) {
+ RowKeyColDesc tmp = rowkeyColumns[i];
+ rowkeyColumns[i] = rowkeyColumns[j];
+ rowkeyColumns[j] = tmp;
+ }
+ req.setCubeDescData(JsonUtil.writeValueAsIndentString(newCubeDesc));
+ res = cubeController.updateCubeDesc(req);
+ Assert.assertTrue(res.getSuccessful());
+
+ resultDesc = getCubeDescByName(TEST_CUBE_NAME);
+ ;
+ Assert.assertNotEquals(newCubeDesc.getSignature(), resultDesc.getSignature());
+ Assert.assertEquals(newCubeDesc.calculateSignature(), resultDesc.getSignature());
+ }
+
+ private void assertUpdateFail(CubeRequest req) throws JsonProcessingException {
+ CubeRequest res = cubeController.updateCubeDesc(req);
+ Assert.assertFalse(res.getSuccessful());
+ }
}