You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ni...@apache.org on 2019/05/27 03:34:31 UTC
[kylin] 01/02: KYLIN-3983 Add extra metadata for measure. Add test
case and example/test_case_data for MeasureManager. Add measure metadata in
sample cube
This is an automated email from the ASF dual-hosted git repository.
nic pushed a commit to branch dynamic-measure
in repository https://gitbox.apache.org/repos/asf/kylin.git
commit 29122d9128c2c8d528f4a2a93b1fe611a055d8dd
Author: yuzhang <sh...@163.com>
AuthorDate: Sun Apr 28 23:46:03 2019 +0800
KYLIN-3983 Add extra metadata for measure. Add test case and example/test_case_data for MeasureManager. Add measure metadata in sample cube
---
.../org/apache/kylin/common/KylinConfigBase.java | 28 +
.../kylin/common/persistence/ResourceStore.java | 1 +
.../kylin/common/persistence/ResourceTool.java | 4 +-
.../org/apache/kylin/cube/CubeDescManager.java | 4 +-
.../java/org/apache/kylin/cube/CubeManager.java | 17 +
.../cube/adapter/AbstractHBaseMappingAdapter.java | 211 +++++++
.../kylin/cube/adapter/IHBaseMappingAdapter.java | 40 ++
.../kylin/cube/adapter/IWiseHBaseMapper.java | 40 ++
.../adapter/MemoryHungryHBaseMappingAdapter.java | 114 ++++
.../cube/adapter/OneCFHBaseMappingAdapter.java | 75 +++
.../java/org/apache/kylin/measure/CubeL2Cache.java | 194 ++++++
.../org/apache/kylin/measure/MeasureInstance.java | 246 ++++++++
.../org/apache/kylin/measure/MeasureManager.java | 701 +++++++++++++++++++++
.../org/apache/kylin/cube/CubeManagerTest.java | 68 +-
.../apache/kylin/measure/MeasureManagerTest.java | 205 ++++++
.../apache/kylin/metadata/model/DateTimeRange.java | 46 ++
.../measure/kylin_sales_cube/BUYER_LEVEL_SUM.json | 9 +
.../template/measure/kylin_sales_cube/GMV_SUM.json | 9 +
.../measure/kylin_sales_cube/SELLER_CNT_HLL.json | 9 +
.../measure/kylin_sales_cube/SELLER_LEVEL_SUM.json | 9 +
.../measure/kylin_sales_cube/TOP_SELLER.json | 9 +
.../measure/kylin_sales_cube/TRANS_CNT.json | 9 +
.../measure/kylin_streaming_cube/TOTAL_AMOUNT.json | 9 +
.../measure/kylin_streaming_cube/TOTAL_QTY.json | 9 +
.../measure/kylin_streaming_cube/_COUNT_.json | 9 +
.../measure/ci_inner_join_cube/BUYER_CONTACT.json | 9 +
.../measure/ci_inner_join_cube/CAL_DT_RAW.json | 9 +
.../measure/ci_inner_join_cube/GMV_CNT.json | 9 +
.../measure/ci_inner_join_cube/GMV_MAX.json | 9 +
.../measure/ci_inner_join_cube/GMV_MIN.json | 9 +
.../measure/ci_inner_join_cube/GMV_SUM.json | 9 +
.../measure/ci_inner_join_cube/ITEM_COUNT_SUM.json | 9 +
.../measure/ci_inner_join_cube/PRICE_RAW.json | 9 +
.../measure/ci_inner_join_cube/SELLER_CONTACT.json | 9 +
.../ci_inner_join_cube/SELLER_FORMAT_HLL.json | 9 +
.../measure/ci_inner_join_cube/SELLER_HLL.json | 9 +
.../ci_inner_join_cube/TEST_COUNT_COLUMN_CNT.json | 9 +
.../TEST_COUNT_DISTINCT_BITMAP.json | 9 +
.../ci_inner_join_cube/TEST_EXTENDED_COLUMN.json | 9 +
.../measure/ci_inner_join_cube/TOP_SELLER.json | 9 +
.../measure/ci_inner_join_cube/TRANS_CNT.json | 9 +
.../measure/ci_inner_join_cube/TRANS_ID_RAW.json | 9 +
.../measure/ci_left_join_cube/BUYER_CONTACT.json | 9 +
.../measure/ci_left_join_cube/CAL_DT_RAW.json | 9 +
.../measure/ci_left_join_cube/GMV_CNT.json | 9 +
.../measure/ci_left_join_cube/GMV_MAX.json | 9 +
.../measure/ci_left_join_cube/GMV_MIN.json | 9 +
.../measure/ci_left_join_cube/GMV_SUM.json | 9 +
.../measure/ci_left_join_cube/GVM_PERCENTILE.json | 9 +
.../measure/ci_left_join_cube/ITEM_COUNT_SUM.json | 9 +
.../measure/ci_left_join_cube/PRICE_RAW.json | 9 +
.../measure/ci_left_join_cube/SELLER_CONTACT.json | 9 +
.../ci_left_join_cube/SELLER_FORMAT_HLL.json | 9 +
.../measure/ci_left_join_cube/SELLER_HLL.json | 9 +
.../ci_left_join_cube/TEST_COUNT_COLUMN_CNT.json | 9 +
.../TEST_COUNT_DISTINCT_BITMAP.json | 9 +
.../ci_left_join_cube/TEST_EXTENDED_COLUMN.json | 9 +
.../measure/ci_left_join_cube/TOP_SELLER.json | 9 +
.../measure/ci_left_join_cube/TRANS_CNT.json | 9 +
.../measure/ci_left_join_cube/TRANS_ID_RAW.json | 9 +
.../measure/fifty_dim_full_build_cube/_COUNT_.json | 9 +
.../localmeta/measure/ssb/TOTAL_REVENUE.json | 9 +
.../localmeta/measure/ssb/TOTAL_SUPPLYCOST.json | 9 +
.../localmeta/measure/ssb/TOTAL_V_REVENUE.json | 9 +
.../localmeta/measure/ssb/_COUNT_.json | 9 +
.../localmeta/measure/ssb_cube1/TOTAL_REVENUE.json | 9 +
.../measure/ssb_cube1/TOTAL_SUPPLYCOST.json | 9 +
.../measure/ssb_cube1/TOTAL_V_REVENUE.json | 9 +
.../localmeta/measure/ssb_cube1/_COUNT_.json | 9 +
.../localmeta/measure/ssb_cube2/TOTAL_REVENUE.json | 9 +
.../measure/ssb_cube2/TOTAL_SUPPLYCOST.json | 9 +
.../measure/ssb_cube2/TOTAL_V_REVENUE.json | 9 +
.../localmeta/measure/ssb_cube2/_COUNT_.json | 9 +
.../localmeta/measure/ssb_cube3/TOTAL_REVENUE.json | 9 +
.../measure/ssb_cube3/TOTAL_SUPPLYCOST.json | 9 +
.../localmeta/measure/ssb_cube3/_COUNT_.json | 9 +
.../TOTAL_REVENUE.json | 9 +
.../TOTAL_SUPPLYCOST.json | 9 +
.../ssb_cube_with_dimention_range/_COUNT_.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../TRANS_CNT.json | 9 +
.../test_kylin_cube_with_slr_empty/GMV_MAX.json | 9 +
.../test_kylin_cube_with_slr_empty/GMV_MIN.json | 9 +
.../test_kylin_cube_with_slr_empty/GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../test_kylin_cube_with_slr_empty/TRANS_CNT.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../SELLER_CNT_HLL.json | 9 +
.../TOP_SELLER.json | 9 +
.../TRANS_CNT.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../SELLER_CNT_HLL.json | 9 +
.../TOP_SELLER.json | 9 +
.../TRANS_CNT.json | 9 +
.../test_kylin_cube_with_slr_ready/GMV_MAX.json | 9 +
.../test_kylin_cube_with_slr_ready/GMV_MIN.json | 9 +
.../test_kylin_cube_with_slr_ready/GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../test_kylin_cube_with_slr_ready/TRANS_CNT.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../TRANS_CNT.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../TRANS_CNT.json | 9 +
.../CAL_DT_RAW.json | 9 +
.../test_kylin_cube_without_slr_empty/GMV_MAX.json | 9 +
.../test_kylin_cube_without_slr_empty/GMV_MIN.json | 9 +
.../test_kylin_cube_without_slr_empty/GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../LEAF_CATEG_ID_RAW.json | 9 +
.../LSTG_FORMAT_NAME_RAW.json | 9 +
.../PRICE_RAW.json | 9 +
.../SITE_EXTENDED_1.json | 9 +
.../SITE_EXTENDED_2.json | 9 +
.../TRANS_CNT.json | 9 +
.../CAL_DT_RAW.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../LEAF_CATEG_ID_RAW.json | 9 +
.../LSTG_FORMAT_NAME_RAW.json | 9 +
.../PRICE_RAW.json | 9 +
.../SELLER_CNT_BITMAP.json | 9 +
.../SELLER_FORMAT_CNT.json | 9 +
.../TOP_SELLER.json | 9 +
.../TRANS_CNT.json | 9 +
.../USER_COUNT_BITMAP.json | 9 +
.../CAL_DT_RAW.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../LEAF_CATEG_ID_RAW.json | 9 +
.../LSTG_FORMAT_NAME_RAW.json | 9 +
.../PRICE_RAW.json | 9 +
.../SELLER_CNT_BITMAP.json | 9 +
.../SELLER_FORMAT_CNT.json | 9 +
.../TOP_SELLER.json | 9 +
.../TRANS_CNT.json | 9 +
.../USER_COUNT_BITMAP.json | 9 +
.../CAL_DT_RAW.json | 9 +
.../GMV_MAX.json | 9 +
.../GMV_MIN.json | 9 +
.../GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../LEAF_CATEG_ID_RAW.json | 9 +
.../LSTG_FORMAT_NAME_RAW.json | 9 +
.../PRICE_RAW.json | 9 +
.../SELLER_CNT_BITMAP.json | 9 +
.../SELLER_FORMAT_CNT.json | 9 +
.../TOP_SELLER.json | 9 +
.../TRANS_CNT.json | 9 +
.../USER_COUNT_BITMAP.json | 9 +
.../CAL_DT_RAW.json | 9 +
.../test_kylin_cube_without_slr_ready/GMV_MAX.json | 9 +
.../test_kylin_cube_without_slr_ready/GMV_MIN.json | 9 +
.../test_kylin_cube_without_slr_ready/GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../LEAF_CATEG_ID_RAW.json | 9 +
.../LSTG_FORMAT_NAME_RAW.json | 9 +
.../PRICE_RAW.json | 9 +
.../SITE_EXTENDED_1.json | 9 +
.../SITE_EXTENDED_2.json | 9 +
.../TRANS_CNT.json | 9 +
.../test_streaming_join_table_cube/GMV_SUM.json | 9 +
.../ITEM_COUNT_SUM.json | 9 +
.../test_streaming_join_table_cube/_COUNT_.json | 9 +
.../measure/test_streaming_table_cube/GMV_SUM.json | 9 +
.../test_streaming_table_cube/ITEM_COUNT_SUM.json | 9 +
.../measure/test_streaming_table_cube/_COUNT_.json | 9 +
.../test_streaming_v2_cube/GMV_PERCENTILE.json | 9 +
.../measure/test_streaming_v2_cube/GMV_SUM.json | 9 +
.../test_streaming_v2_cube/ITEM_COUNT_SUM.json | 9 +
.../measure/test_streaming_v2_cube/_COUNT_.json | 9 +
.../COUNTDISTINCT_LID.json | 9 +
.../COUNTDISTINCT_UID.json | 9 +
.../MAX_EXPERIENCE.json | 9 +
.../MIN_EXPERIENCE.json | 9 +
.../PERCENTILE_REPUTATION.json | 9 +
.../SUM_COINS.json | 9 +
.../test_streaming_v2_user_info_cube/_COUNT_.json | 9 +
examples/test_case_data/measure/MAX_SELLER_ID.json | 11 +
.../measure/ut_jdbc_shard/BUYER_CONTACT.json | 9 +
.../measure/ut_jdbc_shard/CAL_DT_RAW.json | 9 +
.../ut_jdbc_shard/CORR_TRANS_ID_LSTG_SITE_ID.json | 9 +
.../jdbc_source/measure/ut_jdbc_shard/GMV_MAX.json | 9 +
.../jdbc_source/measure/ut_jdbc_shard/GMV_MIN.json | 9 +
.../jdbc_source/measure/ut_jdbc_shard/GMV_SUM.json | 9 +
.../measure/ut_jdbc_shard/GVM_PERCENTILE.json | 9 +
.../measure/ut_jdbc_shard/ITEM_COUNT_SUM.json | 9 +
.../measure/ut_jdbc_shard/PRICE_RAW.json | 9 +
.../measure/ut_jdbc_shard/SELLER_CONTACT.json | 9 +
.../measure/ut_jdbc_shard/SELLER_FORMAT_HLL.json | 9 +
.../measure/ut_jdbc_shard/SELLER_HLL.json | 9 +
.../ut_jdbc_shard/TEST_COUNT_DISTINCT_BITMAP.json | 9 +
.../ut_jdbc_shard/TEST_EXTENDED_COLUMN.json | 9 +
.../measure/ut_jdbc_shard/TOP_SELLER.json | 9 +
.../measure/ut_jdbc_shard/TRANS_CNT.json | 9 +
.../measure/ut_jdbc_shard/TRANS_ID_RAW.json | 9 +
214 files changed, 3773 insertions(+), 5 deletions(-)
diff --git a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
index 93dff1b..33ced89 100644
--- a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
+++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
@@ -484,6 +484,30 @@ public abstract class KylinConfigBase implements Serializable {
return getOptional("kylin.metadata.hbase-client-retries-number", "1");
}
+ public int getMaxMeasureNumberInOneColumn() {
+ return Integer.parseInt(getOptional("kylin.metadata.max-measure-number-in-one-column", "10"));
+ }
+
+ public int getMaxColumnFamilyNumber() {
+ return Integer.parseInt(getOptional("kylin.metadata.max-column-family-number", "10"));
+ }
+
+ public String getAutoHBaseColumnFamilyMapper() {
+ return getOptional("kylin.metadata.auto-hbase-column-family-mapper", "org.apache.kylin.cube.adapter.MemoryHungryHBaseMappingAdapter");
+ }
+
+ public String getHBaseColumnQualifierPrefix() {
+ return getOptional("kylin.metadata.hbase-column-qualifier-prefix", "M");
+ }
+
+ public String getHBaseColumnFamilyNamePrefix() {
+ return getOptional("kylin.metadata.hbase-column-family-name-prefix", "F");
+ }
+
+ public boolean isAutoHBaseMappingEnable() {
+ return Boolean.parseBoolean(getOptional("kylin.cube.is-auto-hbase-mapping-enable", "false"));
+ }
+
// ============================================================================
// DICTIONARY & SNAPSHOT
// ============================================================================
@@ -653,6 +677,10 @@ public abstract class KylinConfigBase implements Serializable {
return Boolean.parseBoolean(getOptional("kylin.cube.is-automerge-enabled", TRUE));
}
+ public boolean isEditableMetricCube() {
+ return Boolean.parseBoolean(getOptional("kylin.cube.is-editable-metric-cube", "false"));
+ }
+
// ============================================================================
// Cube Planner
// ============================================================================
diff --git a/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceStore.java b/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceStore.java
index 7db0eed..dd65e48 100644
--- a/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceStore.java
+++ b/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceStore.java
@@ -80,6 +80,7 @@ abstract public class ResourceStore {
public static final String DRAFT_RESOURCE_ROOT = "/draft";
public static final String USER_ROOT = "/user";
public static final String EXT_SNAPSHOT_RESOURCE_ROOT = "/ext_table_snapshot";
+ public static final String MEASURE_RESOURCE_ROOT = "/measure";
public static final String METASTORE_UUID_TAG = "/UUID";
diff --git a/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceTool.java b/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceTool.java
index 3ff0694..dad643c 100644
--- a/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceTool.java
+++ b/core-common/src/main/java/org/apache/kylin/common/persistence/ResourceTool.java
@@ -28,6 +28,7 @@ import java.util.Locale;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;
+import java.util.stream.Collectors;
import org.apache.kylin.common.KylinConfig;
import org.apache.kylin.common.persistence.ResourceParallelCopier.Stats;
@@ -192,7 +193,8 @@ public class ResourceTool {
public NavigableSet<String> list(KylinConfig config, String path) throws IOException {
ResourceStore store = ResourceStore.getStore(config);
NavigableSet<String> result = store.listResources(path);
- System.out.println("" + result);
+ System.out.println("" + result.stream().collect(Collectors.joining(System.lineSeparator())));
+ System.out.println();
return result;
}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
index a7459c0..ac1df3f 100644
--- a/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
@@ -38,6 +38,7 @@ import org.apache.kylin.cube.model.validation.ValidateContext;
import org.apache.kylin.dimension.DictionaryDimEnc;
import org.apache.kylin.dimension.DimensionEncoding;
import org.apache.kylin.dimension.DimensionEncodingFactory;
+import org.apache.kylin.measure.MeasureManager;
import org.apache.kylin.measure.topn.TopNMeasureType;
import org.apache.kylin.metadata.cachesync.Broadcaster;
import org.apache.kylin.metadata.cachesync.Broadcaster.Event;
@@ -248,10 +249,9 @@ public class CubeDescManager {
}
desc.setSignature(desc.calculateSignature());
-
// save resource
crud.save(desc);
-
+ MeasureManager.getInstance(config).updateMeasuresOnCube(desc);
return desc;
}
}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
index bd9832f..6a6f2b4 100755
--- a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
@@ -44,6 +44,7 @@ import org.apache.kylin.common.util.Dictionary;
import org.apache.kylin.common.util.Pair;
import org.apache.kylin.common.util.RandomUtil;
import org.apache.kylin.cube.cuboid.Cuboid;
+import org.apache.kylin.measure.MeasureManager;
import org.apache.kylin.cube.model.CubeDesc;
import org.apache.kylin.cube.model.SnapshotTableDesc;
import org.apache.kylin.dict.DictionaryInfo;
@@ -347,6 +348,10 @@ public class CubeManager implements IRealizationProvider {
if (update == null || update.getCubeInstance() == null)
throw new IllegalStateException();
+ boolean isNewCube = getCube(update.getCubeInstance().getName()) == null;
+ // init the MeasureInstance Cache first
+ getMeasureManager();
+
CubeInstance cube = update.getCubeInstance();
logger.info("Updating cube instance '{}'", cube.getName());
@@ -395,6 +400,11 @@ public class CubeManager implements IRealizationProvider {
//this is a duplicate call to take care of scenarios where REST cache service unavailable
ProjectManager.getInstance(cube.getConfig()).clearL2Cache(cube.getProject());
+ logger.info("Update MeasureInstance of cube instance: " + cube.getName());
+ if (isNewCube) {
+ getMeasureManager().createMeasuresOnCube(cube);
+ }
+ getMeasureManager().updateSegmentsOnCube(cube, update);
return cube;
}
@@ -498,6 +508,9 @@ public class CubeManager implements IRealizationProvider {
// delete cube instance and cube desc
CubeInstance cube = getCube(cubeName);
+ logger.info("Drop measure on cube first");
+ getMeasureManager().deleteByCube(cube.getProject(), cube.getName());
+
// remove cube and update cache
crud.delete(cube);
Cuboid.clearCache(cube);
@@ -1231,4 +1244,8 @@ public class CubeManager implements IRealizationProvider {
}
return cube;
}
+
+ public MeasureManager getMeasureManager() {
+ return MeasureManager.getInstance(this.config);
+ }
}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/adapter/AbstractHBaseMappingAdapter.java b/core-cube/src/main/java/org/apache/kylin/cube/adapter/AbstractHBaseMappingAdapter.java
new file mode 100644
index 0000000..2b468ef
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/cube/adapter/AbstractHBaseMappingAdapter.java
@@ -0,0 +1,211 @@
+/*
+ * 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.cube.adapter;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.ClassUtil;
+import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.HBaseColumnDesc;
+import org.apache.kylin.cube.model.HBaseColumnFamilyDesc;
+import org.apache.kylin.cube.model.HBaseMappingDesc;
+import org.apache.kylin.measure.MeasureType;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+public abstract class AbstractHBaseMappingAdapter implements IHBaseMappingAdapter, IWiseHBaseMapper {
+
+
+ public static final AbstractHBaseMappingAdapter getHBaseAdapter(KylinConfig config) {
+ try {
+ Class<? extends AbstractHBaseMappingAdapter> adapterClass =
+ ClassUtil.forName(config.getAutoHBaseColumnFamilyMapper(), AbstractHBaseMappingAdapter.class);
+ Constructor<? extends AbstractHBaseMappingAdapter> constructor = adapterClass.getConstructor(KylinConfig.class);
+ return constructor.newInstance(config);
+ } catch (ClassNotFoundException
+ | NoSuchMethodException
+ | IllegalAccessException
+ |InstantiationException
+ | InvocationTargetException e) {
+ throw new IllegalArgumentException("Can't reflect HbaseMapper: " + config.getAutoHBaseColumnFamilyMapper());
+ }
+ }
+
+ protected KylinConfig config;
+ final protected String hBaseColumnFamilyNamePrefix;
+ final protected String hBaseColumnQualifierPrefix;
+
+ protected AbstractHBaseMappingAdapter(KylinConfig config) {
+ this.config = config;
+ hBaseColumnFamilyNamePrefix = this.config.getHBaseColumnFamilyNamePrefix();
+ hBaseColumnQualifierPrefix = this.config.getHBaseColumnQualifierPrefix();
+ }
+
+ protected AbstractHBaseMappingAdapter() {
+ this(KylinConfig.getInstanceFromEnv());
+ }
+
+ @Override
+ public void initHBaseMapping(CubeDesc cubeDesc) {
+ List<MeasureDesc> measures = cubeDesc.getMeasures();
+ if (null == measures) {
+ throw new IllegalArgumentException("cubeDesc.getMeasures got null.");
+ }
+ boolean needResetHBaseMapping = config.isAutoHBaseMappingEnable() && null == cubeDesc.getHbaseMapping();
+ if (needResetHBaseMapping) {
+ HBaseMappingDesc hbaseMapping = getHBaseMappingOnlyOnce(cubeDesc);
+ cubeDesc.setHbaseMapping(hbaseMapping);
+ }
+ cubeDesc.getHbaseMapping().init(cubeDesc);
+ }
+
+ @Override
+ public void initMeasureReferenceToColumnFamilyWithChecking(CubeDesc cubeDesc) {
+ cubeDesc.initMeasureReferenceToColumnFamily();
+ }
+
+ protected HBaseColumnFamilyDesc getSingleColumnCFContain(MeasureDesc measure, String cfName) {
+ HBaseColumnFamilyDesc ret = new HBaseColumnFamilyDesc();
+ HBaseColumnDesc[] hbaseColumnDescs = {getColumnContainSingleMeasure(measure, hBaseColumnQualifierPrefix)};
+ ret.setColumns(hbaseColumnDescs);
+ ret.setName(cfName);
+ return ret;
+ }
+
+ protected HBaseColumnDesc getHBaseColumnDescWithName(String qualifier) {
+ HBaseColumnDesc normColumn = new HBaseColumnDesc();
+ normColumn.setQualifier(qualifier);
+ return normColumn;
+ }
+
+ protected MeasureDesc getMeasureByName(CubeDesc desc, String measureName) {
+ for (MeasureDesc m : desc.getMeasures()) {
+ if (m.getName().equals(measureName)) {
+ return m;
+ }
+ }
+ throw new IllegalStateException(String.format(Locale.ROOT, "Can't find measure %s in cube %s", measureName, desc.getName()));
+ }
+
+
+ protected MeasureType<?> getMeasureType(MeasureDesc measure) {
+ FunctionDesc func = measure.getFunction();
+ func.setReturnType(func.getReturnType());
+ MeasureType<?> measureType = func.getMeasureType();
+ if (null == measureType) {
+ throw new IllegalArgumentException(String.format(Locale.ROOT, "measure type of %s can't be null!", measure.getName()));
+ }
+ return measureType;
+ }
+
+ // only copy reference
+ protected HBaseMappingDesc copy(HBaseMappingDesc needCopy) {
+ List<HBaseColumnFamilyDesc> copyCFs = Lists.newArrayListWithCapacity(needCopy.getColumnFamily().length);
+ for (HBaseColumnFamilyDesc cf : needCopy.getColumnFamily()) {
+ List<HBaseColumnDesc> copyColumns = Lists.newArrayListWithCapacity(cf.getColumns().length);
+ for (HBaseColumnDesc c : cf.getColumns()) {
+ List<String> copyMeasureRefs = Lists.newArrayListWithCapacity(c.getMeasureRefs().length);
+ for (String mf : c.getMeasureRefs()) {
+ copyMeasureRefs.add(mf);
+ }
+ HBaseColumnDesc copyC = getHBaseColumnDescWithName(c.getQualifier());
+ copyC.setMeasureRefs(copyMeasureRefs.toArray(new String[0]));
+ copyColumns.add(copyC);
+ }
+ HBaseColumnFamilyDesc copyCF = new HBaseColumnFamilyDesc();
+ copyCF.setName(cf.getName());
+ copyCF.setColumns(copyColumns.toArray(new HBaseColumnDesc[0]));
+ copyCFs.add(copyCF);
+ }
+ HBaseMappingDesc copyMapping = new HBaseMappingDesc();
+ copyMapping.setColumnFamily(copyCFs.toArray(new HBaseColumnFamilyDesc[0]));
+ return copyMapping;
+ }
+
+ /**
+ *
+ * @param cubeName
+ * @return [index, measure cnt], sorted by measure cnt asc
+ */
+ protected List<Pair<Integer, Integer>> getNormCFIndexInOldMapping(String cubeName){
+ List<Pair<Integer, Integer>> normCFIndexes = Lists.newArrayListWithExpectedSize(5);
+ HBaseColumnFamilyDesc[] cfs = getCubeDescManager().getCubeDesc(cubeName).getHbaseMapping().getColumnFamily();
+ for (int i = 0; i < cfs.length; i++) {
+ if (!cfs[i].isMemoryHungry()) {
+ normCFIndexes.add(new Pair<>(i, getMeasureNumberInCF(cfs[i])));
+ }
+ }
+ normCFIndexes.sort(Comparator.comparingInt(Pair::getSecond));
+ return normCFIndexes;
+ }
+
+ protected int getMeasureNumberInCF(HBaseColumnFamilyDesc cf) {
+ int ret = 0;
+ for (HBaseColumnDesc c : cf.getColumns()) {
+ ret += c.getMeasureRefs().length;
+ }
+ return ret;
+ }
+
+ protected HBaseColumnDesc getColumnContainSingleMeasure(MeasureDesc measure, String qualifier) {
+ return getColumnContainSingleMeasure(measure.getName(), qualifier);
+ }
+
+ protected HBaseColumnDesc getColumnContainSingleMeasure(String measureName, String qualifier) {
+ HBaseColumnDesc hbaseColumn = getHBaseColumnDescWithName(qualifier);
+ hbaseColumn.setMeasureRefs(new String[]{measureName});
+ return hbaseColumn;
+ }
+
+ protected CubeDescManager getCubeDescManager() {
+ return CubeDescManager.getInstance(config);
+ }
+
+ protected int findMaxSuffixOfCF(List<HBaseColumnFamilyDesc> cfs) {
+ if (cfs == null || cfs.size() == 0) {
+ return 0;
+ }
+ List<Integer> cfSuffixes = cfs.stream()
+ .map(cf -> NumberUtils.toInt(cf.getName().replace(hBaseColumnFamilyNamePrefix, "")))
+ .sorted()
+ .collect(Collectors.toList());
+ return cfSuffixes.get(cfSuffixes.size() - 1);
+ }
+
+ protected int findMaxSuffixOfColumn(List<HBaseColumnDesc> cs) {
+ if (cs == null || cs.size() == 0) {
+ return 0;
+ }
+ List<Integer> cSuffixes = cs.stream()
+ .map(cf -> NumberUtils.toInt(cf.getQualifier().replace(hBaseColumnQualifierPrefix, "")))
+ .sorted()
+ .collect(Collectors.toList());
+ return cSuffixes.get(cSuffixes.size() - 1);
+ }
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/adapter/IHBaseMappingAdapter.java b/core-cube/src/main/java/org/apache/kylin/cube/adapter/IHBaseMappingAdapter.java
new file mode 100644
index 0000000..024be21
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/cube/adapter/IHBaseMappingAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cube.adapter;
+
+import org.apache.kylin.cube.model.CubeDesc;
+
+/**
+ * Initialize hbaseMappingDesc in CubeDesc to adapt hbase storage
+ * @author simple
+ */
+public interface IHBaseMappingAdapter {
+
+ /**
+ * Normalize the column family, column and used measure
+ * @param cubeDesc
+ */
+ public void initHBaseMapping(CubeDesc cubeDesc);
+
+ /**
+ * Build measure reference in HBaseColumnDesc and make sure that every measure has been assigned
+ * @param cubeDesc
+ */
+ public void initMeasureReferenceToColumnFamilyWithChecking(CubeDesc cubeDesc);
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/adapter/IWiseHBaseMapper.java b/core-cube/src/main/java/org/apache/kylin/cube/adapter/IWiseHBaseMapper.java
new file mode 100644
index 0000000..e71d0c0
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/cube/adapter/IWiseHBaseMapper.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cube.adapter;
+
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.HBaseMappingDesc;
+
+import java.util.List;
+
+public interface IWiseHBaseMapper {
+ /**
+ * Only called at the first time meet the cube, which must doesn't have hbase mapping;
+ * @param cubeDesc the first meet cube
+ */
+ HBaseMappingDesc getHBaseMappingOnlyOnce(CubeDesc cubeDesc);
+
+ /**
+ * add new measure to old hbase mapping
+ * @param newDesc
+ * @param needAddMeasure
+ * @return
+ */
+ HBaseMappingDesc addMeasure(CubeDesc newDesc, List<String> needAddMeasure);
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/adapter/MemoryHungryHBaseMappingAdapter.java b/core-cube/src/main/java/org/apache/kylin/cube/adapter/MemoryHungryHBaseMappingAdapter.java
new file mode 100644
index 0000000..93b7f96
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/cube/adapter/MemoryHungryHBaseMappingAdapter.java
@@ -0,0 +1,114 @@
+/*
+ * 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.cube.adapter;
+
+import com.google.common.collect.Lists;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.HBaseColumnDesc;
+import org.apache.kylin.cube.model.HBaseColumnFamilyDesc;
+import org.apache.kylin.cube.model.HBaseMappingDesc;
+import org.apache.kylin.measure.MeasureType;
+import org.apache.kylin.metadata.model.MeasureDesc;
+
+import java.util.Comparator;
+import java.util.List;
+
+public class MemoryHungryHBaseMappingAdapter extends AbstractHBaseMappingAdapter {
+
+ public MemoryHungryHBaseMappingAdapter(KylinConfig config) {
+ super(config);
+ }
+
+ @Override
+ public HBaseMappingDesc getHBaseMappingOnlyOnce(CubeDesc cubeDesc) {
+ List<HBaseColumnFamilyDesc> hbaseCFDescs = Lists.newArrayListWithCapacity(4);
+
+ List<String> normMeasures = Lists.newArrayListWithCapacity(cubeDesc.getMeasures().size());
+ for (MeasureDesc measure : cubeDesc.getMeasures()) {
+ MeasureType<?> measureType = getMeasureType(measure);
+ if (measureType.isMemoryHungry()) {
+ HBaseColumnFamilyDesc memoryHungryCF = getSingleColumnCFContain(measure,
+ hBaseColumnFamilyNamePrefix + (hbaseCFDescs.size() + 1));
+ hbaseCFDescs.add(memoryHungryCF);
+ } else {
+ normMeasures.add(measure.getName());
+ }
+ }
+
+ if (normMeasures.size() > 0) {
+ // use to mapping no memory hungry measures
+ HBaseColumnFamilyDesc normalCF = new HBaseColumnFamilyDesc();
+ normalCF.setName(hBaseColumnFamilyNamePrefix + (hbaseCFDescs.size() + 1));
+ HBaseColumnDesc normColumn = getHBaseColumnDescWithName(hBaseColumnQualifierPrefix);
+ normColumn.setMeasureRefs(normMeasures.toArray(new String[normMeasures.size()]));
+ normalCF.setColumns(new HBaseColumnDesc[]{normColumn});
+ hbaseCFDescs.add(normalCF);
+ }
+
+ HBaseMappingDesc hbaseMapping = new HBaseMappingDesc();
+ hbaseMapping.setColumnFamily(hbaseCFDescs.toArray(new HBaseColumnFamilyDesc[hbaseCFDescs.size()]));
+ return hbaseMapping;
+
+ }
+
+ @Override
+ public HBaseMappingDesc addMeasure(CubeDesc newDesc, List<String> needAddMeasure) {
+ if (needAddMeasure == null) {
+ return getHBaseMappingOnlyOnce(newDesc);
+ }
+ HBaseMappingDesc oldMappingCopy = copy(getCubeDescManager().getCubeDesc(newDesc.getName()).getHbaseMapping());
+ if (needAddMeasure.size() == 0) {
+ return oldMappingCopy;
+ }
+ List<HBaseColumnFamilyDesc> cfs = Lists.newArrayList(oldMappingCopy.getColumnFamily());
+ // first element always contain the min number of norm measure
+ List<Pair<Integer, Integer>> normCFIndex = getNormCFIndexInOldMapping(newDesc.getName());
+ for (String measureName : needAddMeasure) {
+ MeasureDesc measureDesc = getMeasureByName(newDesc, measureName);
+ if (getMeasureType(measureDesc).isMemoryHungry()) {
+ // add new CF
+ HBaseColumnFamilyDesc memoryCF = getSingleColumnCFContain(measureDesc, hBaseColumnFamilyNamePrefix + (findMaxSuffixOfCF(cfs) + 1));
+ cfs.add(memoryCF);
+ } else {
+ // find norm CF then add new column to contain this measure,
+ // if don't have an norm CF or achieve max measure count, create one
+ boolean needAddCF = normCFIndex.size() == 0
+ || (normCFIndex.get(0).getSecond() >= config.getMaxMeasureNumberInOneColumn() && cfs.size() <= config.getMaxColumnFamilyNumber());
+ if (needAddCF) {
+ HBaseColumnFamilyDesc normCF = getSingleColumnCFContain(measureDesc, hBaseColumnFamilyNamePrefix + (findMaxSuffixOfCF(cfs) + 1));
+ cfs.add(normCF);
+ normCFIndex.add(new Pair<>(cfs.size() - 1, 1));
+ } else {
+ Pair<Integer, Integer> idxCntPair = normCFIndex.get(0);
+ Integer idx = idxCntPair.getFirst();
+ List<HBaseColumnDesc> normColumn = Lists.newArrayList(cfs.get(idx).getColumns());
+ HBaseColumnDesc newColumn = getColumnContainSingleMeasure(measureDesc, hBaseColumnQualifierPrefix + (findMaxSuffixOfColumn(normColumn) + 1));
+ normColumn.add(newColumn);
+ cfs.get(idx).setColumns(normColumn.toArray(new HBaseColumnDesc[0]));
+ idxCntPair.setSecond(idxCntPair.getSecond() + 1);
+ }
+ normCFIndex.sort(Comparator.comparingInt(Pair::getSecond));
+ }
+ }
+ oldMappingCopy.setColumnFamily(cfs.toArray(new HBaseColumnFamilyDesc[0]));
+ return oldMappingCopy;
+ }
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/adapter/OneCFHBaseMappingAdapter.java b/core-cube/src/main/java/org/apache/kylin/cube/adapter/OneCFHBaseMappingAdapter.java
new file mode 100644
index 0000000..0260736
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/cube/adapter/OneCFHBaseMappingAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.cube.adapter;
+
+import com.google.common.collect.Lists;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.HBaseColumnDesc;
+import org.apache.kylin.cube.model.HBaseColumnFamilyDesc;
+import org.apache.kylin.cube.model.HBaseMappingDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+
+import java.util.List;
+
+/**
+ * All metrics are assigned in one column family. Each metric is assigned into one qualifier
+ */
+public class OneCFHBaseMappingAdapter extends AbstractHBaseMappingAdapter {
+
+ public OneCFHBaseMappingAdapter(KylinConfig config) {
+ super(config);
+ }
+
+ @Override
+ public HBaseMappingDesc getHBaseMappingOnlyOnce(CubeDesc cubeDesc) {
+ // use to mapping no memory hungry measures
+ HBaseColumnFamilyDesc finalColumnFamily = new HBaseColumnFamilyDesc();
+ finalColumnFamily.setName(hBaseColumnFamilyNamePrefix + 1);
+
+ List<HBaseColumnDesc> columnList = Lists.newArrayListWithExpectedSize(cubeDesc.getMeasures().size());
+ List<MeasureDesc> measureDescs = Lists.newArrayList(cubeDesc.getMeasures());
+// measureDescs.sort(Comparator.comparingLong(MeasureDesc::getCreatedTime));
+ for (MeasureDesc measure : measureDescs) {
+ HBaseColumnDesc column = getHBaseColumnDescWithName(hBaseColumnQualifierPrefix + (columnList.size() + 1));
+ column.setMeasureRefs(new String[]{measure.getName()});
+ columnList.add(column);
+ }
+
+ finalColumnFamily.setColumns(columnList.toArray(new HBaseColumnDesc[columnList.size()]));
+
+ HBaseMappingDesc hbaseMapping = new HBaseMappingDesc();
+ hbaseMapping.setColumnFamily(new HBaseColumnFamilyDesc[]{finalColumnFamily});
+ return hbaseMapping;
+ }
+
+ @Override
+ public HBaseMappingDesc addMeasure(CubeDesc newDesc, List<String> needAddMeasure) {
+ // just add column on by one
+ HBaseMappingDesc oldMappingCopy = copy(getCubeDescManager().getCubeDesc(newDesc.getName()).getHbaseMapping());
+ HBaseColumnFamilyDesc columnFamilyDesc = oldMappingCopy.getColumnFamily()[0];
+ List<HBaseColumnDesc> hBaseColumnDescs = Lists.newArrayList(columnFamilyDesc.getColumns());
+ for (String measureName : needAddMeasure) {
+ hBaseColumnDescs.add(getColumnContainSingleMeasure(measureName, hBaseColumnQualifierPrefix + (findMaxSuffixOfColumn(hBaseColumnDescs) + 1)));
+ }
+ columnFamilyDesc.setColumns(hBaseColumnDescs.toArray(new HBaseColumnDesc[0]));
+
+ return oldMappingCopy;
+ }
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/measure/CubeL2Cache.java b/core-cube/src/main/java/org/apache/kylin/measure/CubeL2Cache.java
new file mode 100644
index 0000000..dd5a8b3
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/measure/CubeL2Cache.java
@@ -0,0 +1,194 @@
+/*
+ * 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.measure;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.metadata.model.ISegment;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.stream.Collectors;
+
+public class CubeL2Cache {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CubeL2Cache.class);
+
+ private CubeManager cubeMgr;
+ private Map<String, CubeCache> cubeCaches = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER);
+
+
+ public CubeL2Cache(CubeManager cubeMgr) {
+ this.cubeMgr = cubeMgr;
+ }
+
+ // cat
+ public List<MeasureInstance> getMeasuresOnCubeAllowMiss(String cubeName) {
+ return getMeasuresOnCube(cubeName, true);
+ }
+
+ public List<MeasureInstance> getMeasuresOnCube(String cubeName) {
+ return getMeasuresOnCube(cubeName, false);
+ }
+
+ private List<MeasureInstance> getMeasuresOnCube(String cubeName, boolean allowMiss) {
+ CubeCache cache = getCubeCache(cubeName, allowMiss);
+ if (cache == null) {
+ return Collections.EMPTY_LIST;
+ }
+ return ImmutableList.copyOf(cache.measures);
+ }
+
+ public List<MeasureInstance> getMeasuresOf(String cubeName, String segmentName) {
+ CubeCache cache = getCubeCache(cubeName);
+ if (cache == null) {
+ return Collections.EMPTY_LIST;
+ }
+ List<MeasureInstance> ret = cache.segmentMeasureMap.get(segmentName);
+ if (null == ret) {
+ return Collections.EMPTY_LIST;
+ }
+ return ImmutableList.copyOf(ret);
+ }
+
+ private CubeCache getCubeCache(String cubeName) {
+ return getCubeCache(cubeName, false);
+ }
+
+ private CubeCache getCubeCache(String cubeName, boolean allowMiss) {
+ CubeCache cache = cubeCaches.get(cubeName);
+ if (null == cache) {
+ cache = allowMiss ? reloadCacheAllowMiss(cubeName) : reloadCache(cubeName);
+ }
+ return cache;
+ }
+
+ // delete
+ public CubeCache remove(String cubeName) {
+ return cubeCaches.remove(cubeName);
+ }
+
+ // add
+ public CubeCache reloadCache(String cube) {
+ LOG.debug("Reloading L2 cube cache for " + cube);
+ CubeCache cubeCache = new CubeCache(cube);
+
+ CubeInstance cubeInstance = cubeMgr.getCube(cube);
+ if (cubeInstance == null) {
+ return null;
+ }
+ loadMeasureOnCube(cubeCache, cubeInstance);
+ cubeCaches.put(cube, cubeCache);
+ return cubeCache;
+ }
+
+ public CubeCache reloadCacheAllowMiss(String cube) {
+ LOG.debug("Reloading L2 cube cache(allow miss) for " + cube);
+ CubeCache cubeCache = new CubeCache(cube);
+
+ CubeInstance cubeInstance = cubeMgr.getCube(cube);
+ loadMeasureOnCube(cubeCache, cubeInstance, true);
+ cubeCaches.put(cube, cubeCache);
+ return cubeCache;
+ }
+
+ private void loadMeasureOnCube(CubeCache cubeCache, CubeInstance cubeInstance) {
+ loadMeasureOnCube(cubeCache, cubeInstance, false);
+ }
+
+ private void loadMeasureOnCube(CubeCache cubeCache, CubeInstance cubeInstance, boolean allowMiss) {
+
+ List<String> measureNameFromCube = cubeInstance.getMeasures().stream().map(m -> m.getName()).collect(Collectors.toList());
+ List<String> measureKeyFromL1Cache = getMeasureKeyFromCache(cubeInstance.getName());
+ for (String mk : measureKeyFromL1Cache) {
+ MeasureInstance measure = cubeMgr.getMeasureManager().getMeasureByKey(mk);
+ if (null != measure) {
+ cubeCache.measures.add(measure);
+ // update segment map
+ for (ISegment seg : measure.getSegments()) {
+ if (cubeCache.segmentMeasureMap.get(seg.getName()) == null) {
+ List<MeasureInstance> measuresOverSeg = Lists.newArrayList();
+ measuresOverSeg.add(measure);
+ cubeCache.segmentMeasureMap.put(seg.getName(), measuresOverSeg);
+ } else {
+ cubeCache.segmentMeasureMap.get(seg.getName()).add(measure);
+ }
+ }
+ } else {
+ String msg = String.format(Locale.ROOT, "Measure %s is not found in L1 cache now.", mk);
+ LOG.warn(msg);
+ }
+ }
+ if (cubeCache.measures.size() != measureNameFromCube.size()) {
+ List<String> measureNameFromL2Cache = cubeCache.measures.stream().map(m -> m.getName()).collect(Collectors.toList());
+ String msg = String.format(Locale.ROOT, "measures in cube %s are different with measures in L2 cahe %s", measureNameFromCube, measureNameFromL2Cache);
+ if (allowMiss) {
+ LOG.warn(msg);
+ } else {
+ throw new MissMeasureCacheException(msg);
+ }
+ }
+ }
+
+ private List<String> getMeasureKeyFromCache(String name) {
+ Set<String> cacheKey = cubeMgr.getMeasureManager().getCache().keySet();
+ String pre = name + "/";
+ return cacheKey.stream().filter(s -> s.startsWith(pre)).collect(Collectors.toList());
+ }
+
+ private List<String> getMeasureKeyFromCubeCache(CubeInstance cubeInstance) {
+ return cubeInstance.getMeasures().stream()
+ .map(m -> MeasureInstance.getResourceName(cubeInstance.getName(), m.getName()))
+ .collect(Collectors.toList());
+ }
+
+
+ public static class MissMeasureCacheException extends RuntimeException {
+ public MissMeasureCacheException(Exception e) {
+ super(e);
+ }
+
+ public MissMeasureCacheException(String msg) {
+ super(msg);
+ }
+ }
+
+ private static class CubeCache {
+ private String cubeName;
+ private List<MeasureInstance> measures;
+ // segment name => MeasureInstance s
+ private Map<String, List<MeasureInstance>> segmentMeasureMap;
+
+ CubeCache(String cubeName) {
+ this.cubeName = cubeName;
+ this.measures = Lists.newArrayList();
+ this.segmentMeasureMap = Maps.newHashMap();
+ }
+ }
+
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/measure/MeasureInstance.java b/core-cube/src/main/java/org/apache/kylin/measure/MeasureInstance.java
new file mode 100644
index 0000000..90a5ec0
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/measure/MeasureInstance.java
@@ -0,0 +1,246 @@
+/*
+ * 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.measure;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.Lists;
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.common.util.RandomUtil;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.metadata.model.DateTimeRange;
+import org.apache.kylin.metadata.model.ISegment;
+import org.apache.kylin.metadata.model.MeasureDesc;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.kylin.metadata.model.Segments;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+import static org.apache.kylin.metadata.model.SegmentRange.TSRange;
+
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
+public class MeasureInstance extends RootPersistentEntity {
+ private static final Logger LOG = LoggerFactory.getLogger(MeasureInstance.class);
+
+ public static MeasureInstance createMeasureInstance(MeasureDesc measureDesc, CubeInstance cube) {
+ MeasureInstance measureInstance = new MeasureInstance();
+ measureInstance.setName(measureDesc.getName());
+ measureInstance.setMeasureDesc(measureDesc);
+ measureInstance.setCubeName(cube.getName());
+ measureInstance.setSegments(new Segments<>());
+ measureInstance.setSegmentsName(Lists.newArrayList());
+ measureInstance.setOnline(true);
+ return measureInstance;
+ }
+
+ public static MeasureInstance copy(MeasureInstance needCopy) {
+ MeasureInstance copy = new MeasureInstance();
+ copy.setName(needCopy.getName());
+ copy.setCubeName(needCopy.getCubeName());
+ copy.setSegmentsName(Lists.newArrayList(needCopy.getSegmentsName()));
+ Segments<ISegment> copySegs = new Segments<>();
+ // just copy reference of segments, you can't modify any element in segments here.
+ needCopy.getSegments().forEach(s -> copySegs.add(s));
+ copy.setSegments(copySegs);
+ copy.setOnline(copy.isOnline());
+ copy.setLastModified(needCopy.getLastModified());
+ copy.setUuid(needCopy.getUuid());
+ copy.setDateTimeRanges(needCopy.getDateTimeRanges());
+ return copy;
+ }
+
+ public static String getResourceName(String cubeName, String measureName) {
+ return cubeName + "/" + measureName;
+ }
+
+ @JsonProperty("name")
+ private String name;
+ @JsonProperty("cube_name")
+ private String cubeName;
+ @JsonProperty("segments_name")
+ private List<String> segmentsName;
+ @JsonProperty("segments")
+ @JsonIgnore
+ private Segments<ISegment> segments;
+ @JsonProperty("online")
+ private boolean online = true;
+
+ private MeasureDesc measureDesc;
+
+ private List<DateTimeRange> dateTimeRanges;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getCubeName() {
+ return cubeName;
+ }
+
+ public void setCubeName(String cubeName) {
+ this.cubeName = cubeName;
+ }
+
+ public Segments<ISegment> getSegments() {
+ return segments;
+ }
+
+ public void setSegments(Segments<ISegment> segments) {
+ this.segments = segments;
+ }
+
+ public List<String> getSegmentsName() {
+ return segmentsName;
+ }
+
+ public void setSegmentsName(List<String> segmentsName) {
+ this.segmentsName = segmentsName;
+ }
+
+ public void setOnline(boolean online) {
+ this.online = online;
+ }
+
+ public boolean isOnline() {
+ return online;
+ }
+
+ public List<DateTimeRange> getDateTimeRanges() {
+ return dateTimeRanges;
+ }
+
+ public MeasureDesc getMeasureDesc() {
+ return measureDesc;
+ }
+
+ public void setMeasureDesc(MeasureDesc measureDesc) {
+ this.measureDesc = measureDesc;
+ }
+
+ public void setDateTimeRanges(List<DateTimeRange> dateTimeRanges) {
+ this.dateTimeRanges = dateTimeRanges;
+ }
+
+ public void init(CubeInstance cube) {
+ refreshSegments(cube);
+ this.measureDesc = findMeasureByName(this.name, cube);
+ }
+
+ private MeasureDesc findMeasureByName(String measureName, CubeInstance cube) {
+ for (MeasureDesc m : cube.getMeasures()) {
+ if (m.getName().equals(measureName)) {
+ return m;
+ }
+ }
+ LOG.warn("Can't find measure by name: {}, maybe it has been deleted in CubeDesc: {} ", measureName, cube.getDescriptor().getName());
+ return null;
+ }
+
+ public void refreshSegments(CubeInstance cube) {
+ // refresh segments
+ if (null == this.segments) {
+ this.segments = new Segments<>();
+ }
+ this.segments.clear();
+ Iterator<? extends ISegment> cubeSegIter = cube.getSegments(SegmentStatusEnum.READY).iterator();
+ while (cubeSegIter.hasNext()) {
+ ISegment seg = cubeSegIter.next();
+ if (this.getSegmentsName().contains(seg.getName())) {
+ this.segments.add(seg);
+ }
+ }
+ if (this.segments.size() != this.segmentsName.size()) {
+ throw new IllegalStateException(String.format(Locale.ROOT, "Segment names size doesn't equal segments size. Segment names: %s, name in segments: %s, Cube: %s",
+ this.segmentsName,
+ this.segments.stream().map(ISegment::getName).collect(Collectors.toList()),
+ cubeName));
+ }
+
+ // resort segment name
+ for (int i = 0; i < this.segments.size(); i++) {
+ this.segmentsName.set(i, segments.get(i).getName());
+ }
+
+ // refresh date time ranges
+ if (this.dateTimeRanges == null) {
+ dateTimeRanges = Lists.newArrayListWithCapacity(4);
+ }
+ dateTimeRanges.clear();
+ if (segments.size() == 0) {
+ return;
+ }
+
+
+ long startTime = segments.getTSStart();
+
+ for (int i = 1; i < segments.size(); i++) {
+ TSRange lastTsRange = segments.get(i - 1).getTSRange();
+ TSRange tsRange = segments.get(i).getTSRange();
+ if (tsRange.start.v < lastTsRange.end.v) {
+ throw new IllegalStateException(String.format(Locale.ROOT, "Overlap time range, [%s, %s] [%s, %s]",
+ lastTsRange.start.v, lastTsRange.end.v, tsRange.start.v, tsRange.end.v));
+ } else if (tsRange.start.v > lastTsRange.end.v) {
+ // there have a hole
+ dateTimeRanges.add(DateTimeRange.create(startTime, lastTsRange.end.v));
+ // change cursor
+ startTime = tsRange.start.v;
+ } else {
+ continue;
+ }
+ }
+ long endTime = segments.getTSEnd();
+ dateTimeRanges.add(DateTimeRange.create(startTime, endTime));
+ }
+
+ public String getKey(){
+ return getResourceName(cubeName, name);
+ }
+
+ @Override
+ public String resourceName() {
+ return getKey();
+ }
+
+ public boolean isOnSegment(ISegment s) {
+ return isOnSegment(s.getName());
+ }
+
+ public boolean isOnSegment(String segName) {
+ return segmentsName.contains(segName);
+ }
+
+ public void updateRandomUuid() {
+ setUuid(RandomUtil.randomUUID().toString());
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/core-cube/src/main/java/org/apache/kylin/measure/MeasureManager.java b/core-cube/src/main/java/org/apache/kylin/measure/MeasureManager.java
new file mode 100644
index 0000000..5a0fed1
--- /dev/null
+++ b/core-cube/src/main/java/org/apache/kylin/measure/MeasureManager.java
@@ -0,0 +1,701 @@
+/*
+ * 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.measure;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.persistence.JsonSerializer;
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.common.persistence.Serializer;
+import org.apache.kylin.common.util.AutoReadWriteLock;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.CubeUpdate;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.metadata.MetadataConstants;
+import org.apache.kylin.metadata.cachesync.Broadcaster;
+import org.apache.kylin.metadata.cachesync.CachedCrudAssist;
+import org.apache.kylin.metadata.cachesync.CaseInsensitiveStringCache;
+import org.apache.kylin.metadata.model.ISegment;
+import org.apache.kylin.metadata.model.MeasureDesc;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.metadata.project.RealizationEntry;
+import org.apache.kylin.metadata.realization.RealizationType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.apache.kylin.common.util.AutoReadWriteLock.AutoLock;
+import static org.apache.kylin.metadata.cachesync.Broadcaster.Event.CREATE;
+import static org.apache.kylin.metadata.cachesync.Broadcaster.Event.DROP;
+import static org.apache.kylin.metadata.cachesync.Broadcaster.Event.UPDATE;
+
+public class MeasureManager {
+
+ public static final Serializer<MeasureInstance> MEASURE_SERIALIZER = new JsonSerializer<>(MeasureInstance.class);
+
+ private static final Logger LOG = LoggerFactory.getLogger(MeasureManager.class);
+ public static final String CUBE_MEASURE = "cube_measure";
+
+ public static MeasureManager getInstance(KylinConfig config) {
+ return config.getManager(MeasureManager.class);
+ }
+
+ // called by reflection
+ static MeasureManager newInstance(KylinConfig config) throws IOException {
+ return new MeasureManager(config);
+ }
+
+ // ===============================================
+
+ private KylinConfig config;
+
+ // measure instance store path ==> MeasureInstance
+ private CaseInsensitiveStringCache<MeasureInstance> measureMap;
+ private CubeL2Cache cubeL2Cache;
+
+ private CachedCrudAssist<MeasureInstance> crud;
+
+ private AutoReadWriteLock measureMapLock = new AutoReadWriteLock();
+
+ private MeasureManager(KylinConfig config) throws IOException {
+ LOG.info("Initializing MeasureManager with config " + config);
+ this.config = config;
+ this.measureMap = new CaseInsensitiveStringCache<>(config, "measure");
+ this.cubeL2Cache = new CubeL2Cache(getCubeManager());
+
+ this.crud = new CachedCrudAssist<MeasureInstance>(getStore(), ResourceStore.MEASURE_RESOURCE_ROOT, MeasureInstance.class, measureMap) {
+ @Override
+ protected MeasureInstance initEntityAfterReload(MeasureInstance entity, String resourceName) {
+ CubeInstance cube = getCubeManager().getCube(entity.getCubeName());
+ entity.init(cube);
+
+ return entity;
+ }
+ };
+
+ // touch lower level metadata before registering my listener
+ crud.reloadAll();
+ Broadcaster.getInstance(config).registerListener(new MeasureSyncListener(), CUBE_MEASURE);
+ }
+
+ private class MeasureSyncListener extends Broadcaster.Listener {
+
+ @Override
+ public void onEntityChange(Broadcaster broadcaster, String entity, Broadcaster.Event event, String cacheKey) throws IOException {
+
+ switch (entity) {
+// case MEASURE:
+// triggerByMeasure(broadcaster, entity, event, cacheKey);
+// break;
+// case CUBE:
+// case CUBE_DESC:
+ case CUBE_MEASURE:
+ triggerByCube(broadcaster, entity, event, cacheKey);
+ break;
+ default :
+ break;
+ }
+ }
+
+ private void triggerByCube(Broadcaster broadcaster, String cube, Broadcaster.Event event, String cubeName) throws IOException {
+ if (event == DROP) {
+ removeLocalByCube(cubeName);
+ } else {
+ reloadByCubeQuietly(cubeName);
+ }
+ }
+
+ private void triggerByMeasure(Broadcaster broadcaster, String measure, Broadcaster.Event event, String measureKey) {
+ if (event == DROP) {
+ removeLocal(measureKey);
+ } else {
+ reloadQuietly(measureKey);
+ }
+ }
+
+ }
+
+ private MeasureInstance reloadQuietly(String cacheKey) {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ MeasureInstance ret = crud.reloadQuietly(cacheKey);
+ cubeL2Cache.reloadCache(ret.getCubeName());
+ return ret;
+ }
+ }
+
+ private List<MeasureInstance> reloadByCubeQuietly(String cubeName) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ CubeInstance cube = getCubeManager().getCube(cubeName);
+ if (cube == null) {
+ LOG.warn("Can't find cube {} in cache, it's missing or unload yet, so kylin can't reload cache of measures on cube. you can trigger this reload process again by update this cube!");
+ return Collections.EMPTY_LIST;
+ }
+ // remove L1 cache
+ getMeasuresInCubeAllowMiss(cube.getProject(), cube.getName()).stream()
+ .forEach(m -> measureMap.removeLocal(m.getKey()));
+
+ List<String> paths = getStore().collectResourceRecursively(ResourceStore.MEASURE_RESOURCE_ROOT + "/" + cube.getName(), MetadataConstants.FILE_SURFIX);
+
+ List<MeasureInstance> ret = Lists.newArrayListWithCapacity(paths.size());
+ paths.forEach(p -> ret.add(crud.reloadAt(p)));
+ cubeL2Cache.reloadCache(cubeName);
+ return ImmutableList.copyOf(ret);
+ }
+ }
+
+ public ResourceStore getStore() {
+ return ResourceStore.getStore(this.config);
+ }
+
+ public MeasureInstance getMeasure(String cubeName, String measureName) {
+ try (AutoLock lock = measureMapLock.lockForRead()) {
+ return getMeasureByKey(MeasureInstance.getResourceName(cubeName, measureName));
+ }
+ }
+
+ public MeasureInstance getMeasureByKey(String key) {
+ try (AutoLock lock = measureMapLock.lockForRead()) {
+ return measureMap.get(key);
+ }
+ }
+
+ public List<MeasureInstance> getMeasuresOnSegment(String projectName, String cubeName, String segmentName) {
+ try (AutoLock lock = measureMapLock.lockForRead()) {
+ return cubeL2Cache.getMeasuresOf(cubeName, segmentName);
+ }
+ }
+
+ public List<MeasureInstance> getMeasuresInCube(String projectName, String cubeName) {
+ try (AutoLock lock = measureMapLock.lockForRead()) {
+ return cubeL2Cache.getMeasuresOnCube(cubeName);
+ }
+ }
+
+ /**
+ * Sometimes, CubeDesc in cache contain more measures than in Measures in cache, or vice versa.
+ * this call return cache may miss those measures. Those measure will be restored after CubeDesc update
+ * @param projectName
+ * @param cubeName
+ * @return
+ */
+ public List<MeasureInstance> getMeasuresInCubeAllowMiss(String projectName, String cubeName) {
+ try (AutoLock lock = measureMapLock.lockForRead()) {
+ // try get don't allow miss
+ return cubeL2Cache.getMeasuresOnCube(cubeName);
+ } catch (CubeL2Cache.MissMeasureCacheException e) {
+ LOG.info("There have some missing measures. cause by: " + e.getLocalizedMessage());
+ return cubeL2Cache.getMeasuresOnCubeAllowMiss(cubeName);
+ }
+ }
+
+ /**
+ * create and announce
+ * @param cube
+ * @return
+ * @throws IOException
+ */
+ public List<MeasureInstance> createMeasuresOnCube(CubeInstance cube) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ boolean existed = cubeL2Cache.getMeasuresOnCubeAllowMiss(cube.getName()).size() != 0;
+ List<MeasureDesc> measures = cube.getMeasures();
+ List<MeasureInstance> needSaveMeasures = measures.stream()
+ .map(m -> MeasureInstance.createMeasureInstance(m, cube))
+ .collect(Collectors.toList());
+
+ return batchSaveCubeMeasure(needSaveMeasures, cube.getName(), existed);
+ }
+ }
+
+ // don't announce
+ private MeasureInstance createMeasureAlone(MeasureInstance measureInstance) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ createInStore(measureInstance);
+ // save in cache
+ return createCache(measureInstance);
+ }
+ }
+
+ private void createInStore(MeasureInstance measureInstance) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ // save meta data
+ getStore().checkAndPutResource(getResourcePath(measureInstance), measureInstance, MEASURE_SERIALIZER);
+ }
+ }
+
+ private MeasureInstance createCache(MeasureInstance measureInstance) {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ // save in cache
+ measureMap.putLocal(measureInstance.getKey(), measureInstance);
+ cubeL2Cache.reloadCache(measureInstance.getCubeName());
+ return measureInstance;
+ }
+ }
+
+ public List<MeasureInstance> batchSaveCubeMeasure(List<MeasureInstance> measures, String cubeName, boolean existed) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ // save in store
+ batchSaveCubeMeasureInStore(measures);
+
+ // announce
+ announceCubeMeasureEvent(existed ? UPDATE : CREATE, cubeName);
+
+ // save in cache
+ return batchSaveCubeMeasureInCache(measures, cubeName);
+ }
+ }
+
+ private List<MeasureInstance> batchSaveCubeMeasureInStore(List<MeasureInstance> measures) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ // save in store
+ for (MeasureInstance m : measures) {
+ if (null == m.getUuid()) {
+ m.updateRandomUuid();
+ }
+ createInStore(m);
+ }
+ return measures;
+ }
+ }
+
+ private List<MeasureInstance> batchSaveCubeMeasureInCache(List<MeasureInstance> measures, String cubeName) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ // save in cache
+ for (MeasureInstance m : measures) {
+ measureMap.putLocal(m.getKey(), m);
+ }
+ cubeL2Cache.reloadCache(cubeName);
+
+ return measures;
+ }
+ }
+
+ // ================delete====================
+
+ private MeasureInstance deleteInStore(MeasureInstance m) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ if (m.getSegmentsName().size() > 0) {
+ throw new IllegalStateException(String.format(Locale.ROOT, "Can't delete measure %s, please delete the contained segments first. %s", m.getName(), m.getSegmentsName()));
+ }
+ getStore().deleteResource(getResourcePath(m));
+ return m;
+ }
+ }
+
+ private MeasureInstance deleteCache(MeasureInstance m) {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ measureMap.remove(m.getKey());
+ cubeL2Cache.reloadCache(m.getCubeName());
+ return m;
+ }
+ }
+
+ public List<MeasureInstance> deleteByCube(String projectName, String cubeName) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ // delete meta data
+ List<MeasureInstance> needDrop = deleteInStoreByCube(projectName, cubeName);
+ if (null != needDrop && needDrop.size() > 0) {
+ // announce delete cube measure
+ announceCubeMeasureEvent(DROP, cubeName);
+ // delete in cache
+ removeLocalByCube(cubeName);
+ }
+ return needDrop;
+ }
+ }
+
+ private List<MeasureInstance> removeLocalByCube(String cubeName) {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<MeasureInstance> needRemove = cubeL2Cache.getMeasuresOnCube(cubeName);
+ if (needRemove.size() == 0) {
+ // get from L1 cache
+ needRemove = getMeasuresInCubeFromL1Cache(cubeName);
+ }
+ // remove CubeL2Cache
+ cubeL2Cache.remove(cubeName);
+ // remove measureMap
+ needRemove.forEach(m -> removeL1Cache(m.getKey()));
+ return needRemove;
+ }
+ }
+
+ private List<MeasureInstance> getMeasuresInCubeFromL1Cache(String cubeName) {
+ String prefix = cubeName + "/";
+ return measureMap.keySet()
+ .stream()
+ .filter(k -> k.startsWith(prefix))
+ .map(k -> measureMap.get(k))
+ .collect(Collectors.toList());
+ }
+
+ private MeasureInstance removeL1Cache(String key) {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ MeasureInstance ret = measureMap.get(key);
+ if (null != ret) {
+ measureMap.removeLocal(key);
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * remove L1 cache and reload L2 cache by measure key
+ * @param key
+ * @return
+ */
+ private MeasureInstance removeLocal(String key) {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ MeasureInstance ret = removeL1Cache(key);
+ if (null != ret) {
+ cubeL2Cache.reloadCache(ret.getCubeName());
+// cubeL2Cache.reloadCacheAllowMiss(ret.getCubeName());
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * just delete meta data in store, don't broadcast
+ * @param projectName
+ * @param cubeName
+ * @return
+ */
+ private List<MeasureInstance> deleteInStoreByCube(String projectName, String cubeName) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<MeasureInstance> needDrop = getMeasuresInCube(projectName, cubeName);
+ ResourceStore store = getStore();
+ for (MeasureInstance m : needDrop) {
+ store.deleteResource(getResourcePath(m));
+ }
+ return needDrop;
+ }
+ }
+
+ public void deleteSegmentByName(CubeInstance cube, String segmentName) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<MeasureInstance> updated = deleteSegInMeasure(cube, segmentName);
+ batchSaveCubeMeasure(updated, cube.getName(), true);
+ }
+ }
+
+ private List<MeasureInstance> deleteSegInMeasure(CubeInstance cube, String segmentName) {
+ List<MeasureInstance> measuresOnSegment = getMeasuresOnSegment(cube.getProject(), cube.getName(), segmentName);
+ if (measuresOnSegment.size() <= 0) {
+ return measuresOnSegment;
+ }
+ List<MeasureInstance> updated = measuresOnSegment.stream()
+ .map(m -> MeasureInstance.copy(m))
+ .collect(Collectors.toList());
+ for (MeasureInstance m : updated) {
+ if (!m.getSegmentsName().remove(segmentName)) {
+ LOG.warn("Can't find segment by name {} in measure {}.", segmentName, m.getKey());
+ continue;
+ }
+ m.refreshSegments(cube);
+ }
+ return updated;
+ }
+
+ private List<MeasureInstance> batchDeleteSegInMeasure(CubeInstance cube, List<String> segmentsName) {
+ List<MeasureInstance> measuresOnCube = getMeasuresInCube(cube.getProject(), cube.getName());
+ if (measuresOnCube.size() <= 0) {
+ return measuresOnCube;
+ }
+ List<MeasureInstance> updated = measuresOnCube.stream()
+ .map(m -> MeasureInstance.copy(m))
+ .collect(Collectors.toList());
+ for (MeasureInstance m : updated) {
+ if (m.getSegmentsName().removeIf(s -> segmentsName.contains(s))) {
+ m.refreshSegments(cube);
+ }
+ }
+ return updated;
+ }
+
+ /**
+ *
+ * if segsToDrop is null it's mean delete all;
+ */
+ public void deleteSegments(CubeInstance cube, ISegment... segsToDrop) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<String> needDrop = Lists.newArrayList(segsToDrop).stream().map(ISegment::getName).collect(Collectors.toList());
+ deleteSegmentsByName(cube, needDrop);
+ }
+ }
+
+ private void deleteSegmentsByName(CubeInstance cube, List<String> needDrop) throws IOException {
+ // save in store
+ List<MeasureInstance> updated = batchDeleteSegInMeasure(cube, needDrop);
+ List<MeasureInstance> storedMeasures = batchSaveCubeMeasureInStore(updated);
+ // announce
+ announceUpdateCubeMeasure(cube.getName());
+ // save in cache
+ batchSaveCubeMeasureInCache(storedMeasures, cube.getName());
+ }
+
+ public void deleteAllSegments(CubeInstance cube) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<String> needDrop;
+ LOG.info("Delete all segments in cube.", cube.getName());
+ needDrop = cube.getSegments().stream().map(ISegment::getName).collect(Collectors.toList());
+
+ // save in store
+ deleteSegmentsByName(cube, needDrop);
+ }
+ }
+
+ // ================update=====================
+ /**
+ * if some measures on cube have been modified. add or delete measure
+ * @param cubeDesc
+ * @return updated measures in cube
+ */
+ public List<MeasureInstance> updateMeasuresOnCube(CubeDesc cubeDesc) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<CubeInstance> cubesByDesc = getCubeManager().getCubesByDesc(cubeDesc.getName());
+ List<MeasureInstance> ret = Lists.newArrayList();
+ for (CubeInstance cube : cubesByDesc) {
+ ret.addAll(updateMeasuresOnCube(cube));
+ }
+
+ return ret;
+ }
+ }
+
+ public List<MeasureInstance> updateSegmentsOnCube(CubeInstance updatedCube, CubeUpdate update) throws IOException {
+ ISegment[] toAddSegs = getReadySegments(update.getToAddSegs());
+ ISegment[] toUpdateSegs = getReadySegments(update.getToUpdateSegs());
+ ISegment[] toRemoveSegs = getReadySegments(update.getToRemoveSegs());
+
+ boolean needToUpdateSegs = toAddSegs.length > 0 || toUpdateSegs.length > 0 || toRemoveSegs.length > 0;
+
+ if (!needToUpdateSegs) {
+ return Collections.emptyList();
+ }
+ /* there may have overlap between toRemoveSegs and toUpdateSegs,
+ * because they are collected by their uuid.
+ * So we remove toRemoveSegs firstly, then add toUpdateSegs.
+ */
+ List<MeasureInstance> newMeasures = batchDeleteSegInMeasure(updatedCube,
+ Arrays.stream(toRemoveSegs).map(m -> m.getName()).collect(Collectors.toList()));
+
+ Set<String> toAddSegNames = Arrays.stream(toAddSegs).map(ISegment::getName).collect(Collectors.toSet());
+ Set<String> toUpdateSegNames = Arrays.stream(toUpdateSegs).map(ISegment::getName).collect(Collectors.toSet());
+
+ for (int i = 0;
+ (toAddSegNames.size() > 0 || toUpdateSegNames.size() > 0)
+ && i < newMeasures.size(); i++) {
+ MeasureInstance measure = newMeasures.get(i);
+ Set<String> newSegsName = Sets.newHashSet(measure.getSegmentsName());
+ newSegsName.addAll(toAddSegNames);
+ newSegsName.addAll(toUpdateSegNames);
+ List<String> newSegsNameList = Lists.newArrayList(newSegsName);
+ Collections.sort(newSegsNameList);
+ measure.setSegmentsName(newSegsNameList);
+ measure.refreshSegments(updatedCube);
+ }
+ batchSaveCubeMeasure(newMeasures, updatedCube.getName(), true);
+ return newMeasures;
+ }
+
+ private ISegment[] getReadySegments(ISegment[] segs) {
+ if (null == segs) {
+ return new ISegment[]{};
+ }
+ return Arrays.stream(segs)
+ .filter(s -> s.getStatus().equals(SegmentStatusEnum.READY))
+ .toArray(ISegment[]::new);
+ }
+
+ private List<MeasureInstance> updateMeasuresOnCube(CubeInstance cube) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ List<MeasureInstance> cachedMeasureOnCube = getMeasuresInCubeAllowMiss(cube.getProject(), cube.getName());
+ List<MeasureInstance> needDrop = Lists.newArrayListWithCapacity(5);
+ List<MeasureInstance> needAdd = Lists.newArrayListWithCapacity(6);
+
+ // find need drop
+ Set<String> latestMeasures = cube.getMeasures().stream().map(MeasureDesc::getName).collect(Collectors.toSet());
+ cachedMeasureOnCube.stream()
+ .filter(cm -> !latestMeasures.contains(cm.getName()))
+ .forEach(cm -> needDrop.add(cm));
+ // find need add
+ Set<String> curMeasureNames = cachedMeasureOnCube.stream().map(MeasureInstance::getName).collect(Collectors.toSet());
+ cube.getMeasures().stream()
+ .filter(m -> !curMeasureNames.contains(m.getName()))
+ .forEach(m -> needAdd.add(MeasureInstance.createMeasureInstance(m, cube)));
+
+ for (MeasureInstance m : needAdd) {
+ createInStore(m);
+ }
+
+ for (MeasureInstance m : needDrop) {
+ deleteInStore(m);
+ removeLocal(m.getKey());
+ }
+
+ announceUpdateCubeMeasure(cube.getName());
+
+ reloadByCubeQuietly(cube.getName());
+
+ return getMeasuresInCube(cube.getProject(), cube.getName());
+ }
+ }
+
+ /**
+ *
+ * @param project
+ * @param cubeName
+ * @param updatedMeasures
+ * @return
+ * @throws IOException
+ */
+ public List<MeasureInstance> updateMeasures(String project, String cubeName, List<MeasureInstance> updatedMeasures) throws IOException {
+ try (AutoLock lock = measureMapLock.lockForWrite()) {
+ return batchSaveCubeMeasure(updatedMeasures, cubeName, true);
+ }
+ }
+
+ private String getResourcePath(MeasureInstance m) {
+ return ResourceStore.MEASURE_RESOURCE_ROOT + "/" + m.resourceName() + MetadataConstants.FILE_SURFIX;
+ }
+
+ public AutoReadWriteLock getMeasureMapLock() {
+ return measureMapLock;
+ }
+
+ private CubeManager getCubeManager(){
+ return CubeManager.getInstance(config);
+ }
+
+ private void announceUpdateCubeMeasure(String cubeName) {
+ announceCubeMeasureEvent(UPDATE, cubeName);
+ }
+
+ private void announceCubeMeasureEvent(Broadcaster.Event e, String cubeName) {
+ measureMap.getBroadcaster().announce(CUBE_MEASURE, e.getType(), cubeName);
+ }
+
+ public CaseInsensitiveStringCache<MeasureInstance> getCache() {
+ return measureMap;
+ }
+
+ public static void main(String[] args) throws IOException {
+ String errInputMsg =
+ "Error argument. Usage: init cube cubeName \n" +
+ " project projectName \n" +
+ " all";
+ if (args.length < 1 || !args[0].equals("init")) {
+ LOG.error(errInputMsg);
+ return;
+ }
+ switch (args[1]) {
+ case "all":
+ // init all cube
+ initAllCube();
+ break;
+ case "project":
+ // init by project
+ String projectName = args[2];
+ initByProject(projectName);
+ break;
+ case "cube":
+ // init by project
+ String cubeName = args[2];
+ initialCubeMeasure(cubeName);
+ break;
+ default:
+ LOG.error(errInputMsg);
+ break;
+ }
+
+ return;
+ }
+
+ private static void initAllCube() throws IOException {
+ KylinConfig config = KylinConfig.getInstanceFromEnv();
+ CubeManager cubeMgr = CubeManager.getInstance(config);
+ List<CubeInstance> allCubInstance = cubeMgr.listAllCubes();
+ for (CubeInstance cube : allCubInstance) {
+ initialCubeMeasure(cube.getName());
+ }
+ }
+
+ private static void initByProject(String projectName) throws IOException {
+ KylinConfig config = KylinConfig.getInstanceFromEnv();
+ LOG.info("Initialize all cube measure under project " + projectName);
+ ProjectInstance project = ProjectManager.getInstance(config).getProject(projectName);
+ Preconditions.checkNotNull(project, "Can't find project " + projectName);
+ List<RealizationEntry> realizationEntries = project.getRealizationEntries(RealizationType.CUBE);
+ for (RealizationEntry r : realizationEntries) {
+ String cubeName = r.getRealization();
+ initialCubeMeasure(cubeName);
+ }
+ }
+
+ private static void initialCubeMeasure(String cubeName) throws IOException {
+ KylinConfig config = KylinConfig.getInstanceFromEnv();
+ CubeInstance cube = CubeManager.getInstance(config).getCube(cubeName);
+ if (null == cube) {
+ LOG.error(String.format(Locale.ROOT, "Can't find cube by project: %s, cube: %s.", cubeName));
+ return;
+ }
+
+ List<MeasureInstance> measures = cube.getMeasures().stream()
+ .map(m -> MeasureInstance.createMeasureInstance(m, cube))
+ .collect(Collectors.toList());
+ List<String> segsName = cube.getSegments(SegmentStatusEnum.READY).stream()
+ .map(ISegment::getName)
+ .collect(Collectors.toList());
+ MeasureManager measureManager = MeasureManager.getInstance(config);
+ Iterator<MeasureInstance> iter = measures.iterator();
+
+ while (iter.hasNext()) {
+ MeasureInstance m = iter.next();
+ MeasureInstance measureInStore = measureManager.getMeasure(m.getCubeName(), m.getName());
+ if (null != measureInStore) {
+ LOG.info(m.getKey() + " already exist, won't initialize it. you can delete it first.");
+ m.setUuid(measureInStore.getUuid());
+ m.setLastModified(measureInStore.getLastModified());
+ iter.remove();
+ }
+ m.setSegmentsName(segsName);
+ try {
+ m.refreshSegments(cube);
+ } catch (IllegalStateException e){
+ LOG.error("Error: ", e);
+ continue;
+ }
+ }
+
+ measureManager.batchSaveCubeMeasureInStore(measures);
+ }
+}
diff --git a/core-cube/src/test/java/org/apache/kylin/cube/CubeManagerTest.java b/core-cube/src/test/java/org/apache/kylin/cube/CubeManagerTest.java
index 7a102bb..907e6b5 100644
--- a/core-cube/src/test/java/org/apache/kylin/cube/CubeManagerTest.java
+++ b/core-cube/src/test/java/org/apache/kylin/cube/CubeManagerTest.java
@@ -31,6 +31,8 @@ import org.apache.kylin.common.KylinConfig;
import org.apache.kylin.common.persistence.ResourceStore;
import org.apache.kylin.common.util.LocalFileMetadataTestCase;
import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.measure.MeasureInstance;
+import org.apache.kylin.measure.MeasureManager;
import org.apache.kylin.metadata.model.SegmentRange;
import org.apache.kylin.metadata.model.SegmentRange.TSRange;
import org.apache.kylin.metadata.model.SegmentStatusEnum;
@@ -38,6 +40,7 @@ import org.apache.kylin.metadata.project.ProjectInstance;
import org.apache.kylin.metadata.project.ProjectManager;
import org.apache.kylin.metadata.realization.RealizationStatusEnum;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -79,13 +82,24 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
// clean legacy in case last run failed
store.deleteResource("/cube/a_whole_new_cube.json");
-
+ for (String measureRes : store.collectResourceRecursively("/measure/a_whole_new_cube", ".json")) {
+ store.deleteResource(measureRes);
+ }
CubeDescManager cubeDescMgr = getCubeDescManager();
CubeDesc desc = cubeDescMgr.getCubeDesc("test_kylin_cube_with_slr_desc");
CubeInstance createdCube = cubeMgr.createCube("a_whole_new_cube", ProjectInstance.DEFAULT_PROJECT_NAME, desc,
null);
assertTrue(createdCube.equals(cubeMgr.getCube("a_whole_new_cube")));
+ // test MeasureManager
+ assertTrue(getStore().collectResourceRecursively("/measure/a_whole_new_cube", ".json").size() == createdCube.getMeasures().size());
+ List<MeasureInstance> measuresInCreatedCube = getMeasureManager().getMeasuresInCube(createdCube.getProject(), createdCube.getName());
+ assertTrue(createdCube.getMeasures().size() == measuresInCreatedCube.size());
+ for (MeasureInstance m : measuresInCreatedCube) {
+ assertTrue(createdCube.getMeasures().contains(m.getMeasureDesc()));
+ assertTrue(m.getSegments().size() == 0);
+ }
+
assertTrue(prjMgr.listAllRealizations(ProjectInstance.DEFAULT_PROJECT_NAME).contains(createdCube));
CubeInstance droppedCube = CubeManager.getInstance(getTestConfig()).dropCube("a_whole_new_cube", false);
@@ -94,6 +108,10 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
assertTrue(!prjMgr.listAllRealizations(ProjectInstance.DEFAULT_PROJECT_NAME).contains(droppedCube));
assertNull(CubeManager.getInstance(getTestConfig()).getCube("a_whole_new_cube"));
+
+ List<MeasureInstance> measuresInDroppedCube = getMeasureManager().getMeasuresInCube(droppedCube.getProject(), droppedCube.getName());
+ assertTrue(measuresInDroppedCube.size() == 0);
+ assertTrue(getStore().collectResourceRecursively("/measure/a_whole_new_cube", ".json").size() == 0);
}
@Test
@@ -109,7 +127,9 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
// no segment at first
assertEquals(0, cube.getSegments().size());
-
+ for (MeasureInstance m : getMeasureManager().getMeasuresInCube(cube.getProject(), cube.getName())) {
+ assertTrue(m.getSegmentsName().size() == 0);
+ }
// append first
CubeSegment seg1 = mgr.appendSegment(cube, new TSRange(0L, 1000L), null, null, null);
mgr.updateCubeSegStatus(seg1, SegmentStatusEnum.READY);
@@ -119,10 +139,20 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
cube = mgr.getCube(cube.getName());
assertEquals(2, cube.getSegments().size());
+ for (MeasureInstance m : getMeasureManager().getMeasuresInCube(cube.getProject(), cube.getName())) {
+ assertEquals(2, m.getSegmentsName().size());
+ }
SegmentRange mergedSeg = cube.autoMergeCubeSegments();
assertTrue(mergedSeg != null);
+
+ for (MeasureInstance m : getMeasureManager().getMeasuresInCube(cube.getProject(), cube.getName())) {
+ assertEquals(1, m.getSegmentsName().size());
+ assertEquals(1, m.getDateTimeRanges().size());
+ assertTrue(0L == m.getSegments().get(0).getTSRange().start.v);
+ assertTrue(2000L == m.getSegments().get(0).getTSRange().end.v);
+ }
}
}
@@ -181,6 +211,13 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
assertTrue(cube.getSegmentById(seg5.getUuid()) != null
&& cube.getSegmentById(seg5.getUuid()).getStatus() == SegmentStatusEnum.READY);
+ for (MeasureInstance m : getMeasureManager().getMeasuresInCube(cube.getProject(), cube.getName())) {
+ assertTrue(m.getSegmentsName().size() == 4);
+ assertEquals(seg1.getName(), m.getSegments().get(0).getName());
+ assertEquals(seg2.getName(), m.getSegments().get(1).getName());
+ assertEquals(seg4.getName(), m.getSegments().get(2).getName());
+ assertEquals(seg5.getName(), m.getSegments().get(3).getName());
+ }
}
@Test
@@ -246,6 +283,12 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
assertTrue(cube.getSegmentById(merge2.getUuid()) != null
&& cube.getSegmentById(merge2.getUuid()).getStatus() == SegmentStatusEnum.NEW);
+ for (MeasureInstance m : getMeasureManager().getMeasuresInCube(cube.getProject(), cube.getName())) {
+ assertTrue(m.getSegmentsName().size() == 3);
+ assertEquals(merge1.getName(), m.getSegments().get(0).getName());
+ assertEquals(seg3.getName(), m.getSegments().get(1).getName());
+ assertEquals(seg4.getName(), m.getSegments().get(2).getName());
+ }
}
@Test
@@ -436,8 +479,29 @@ public class CubeManagerTest extends LocalFileMetadataTestCase {
assertEquals(segment._getDateRangeEnd(), SECOND_BUILD_DATE_END.longValue());
}
+ @Test
+ public void testDeleteSegment() throws IOException {
+ KylinConfig config = getTestConfig();
+ CubeManager cubeMgr = CubeManager.getInstance(config);
+
+ String cubeName = "test_kylin_cube_with_slr_ready_3_segments";
+
+ CubeInstance cube = cubeMgr.getCube(cubeName);
+ int segNumber = cube.getSegments().size();
+
+ CubeSegment toRemoveSeg = cube.getSegment("19691231160000_20131112000000", null);
+ cubeMgr.updateCubeDropSegments(cube, toRemoveSeg);
+
+ int newSegNumber = cubeMgr.getCube(cubeName).getSegments().size();
+
+ Assert.assertTrue(segNumber == newSegNumber + 1);
+ }
public CubeDescManager getCubeDescManager() {
return CubeDescManager.getInstance(getTestConfig());
}
+
+ private MeasureManager getMeasureManager() {
+ return MeasureManager.getInstance(getTestConfig());
+ }
}
diff --git a/core-cube/src/test/java/org/apache/kylin/measure/MeasureManagerTest.java b/core-cube/src/test/java/org/apache/kylin/measure/MeasureManagerTest.java
new file mode 100644
index 0000000..22a10f8
--- /dev/null
+++ b/core-cube/src/test/java/org/apache/kylin/measure/MeasureManagerTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.measure;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.kylin.common.persistence.ResourceTool;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.common.util.LocalFileMetadataTestCase;
+import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.CubeSegment;
+import org.apache.kylin.cube.adapter.AbstractHBaseMappingAdapter;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.HBaseMappingDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.log4j.BasicConfigurator;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class MeasureManagerTest extends LocalFileMetadataTestCase {
+ private static final String MEASURE_DATA_DIR = "../examples/test_case_data/measure/";
+ private static final String MEASURE_DATA_SUFFIX = ".json";
+
+ @Before
+ public void setUp() throws Exception {
+ BasicConfigurator.configure();
+ this.createTestMetadata();
+ }
+
+ @After
+ public void after() throws Exception {
+ this.cleanupTestMetadata();
+ }
+
+ @Test
+ public void testInitAllCube() throws IOException {
+ ResourceTool.main(new String[]{"remove", "/measure"});
+ MeasureManager.main(new String[]{"init", "all"});
+ // clear manager for reload
+ getTestConfig().clearManagers();
+
+ List<CubeInstance> allCubes = getCubeManager().listAllCubes();
+
+ for (CubeInstance cube : allCubes) {
+ Set<MeasureDesc> measureFromCubeDesc = Sets.newHashSet(cube.getMeasures());
+ Set<MeasureDesc> measureFromCache = getMeasureManager()
+ .getMeasuresInCube(cube.getProject(), cube.getName())
+ .stream()
+ .map(m -> m.getMeasureDesc())
+ .collect(Collectors.toSet());
+ assertEquals(measureFromCubeDesc, measureFromCache);
+ }
+ }
+
+ @Test
+ public void testAddMeasureOnNewCube() throws IOException {
+ String newCubeName = "ci_inner_join_cube";
+ CubeInstance cubeInstance = getCubeManager().getCube(newCubeName);
+ CubeDesc cubeDesc = cubeInstance.getDescriptor();
+ MeasureDesc newMeasure = getMAX_SELLER_ID();
+ CubeDesc updatedCubeDesc = addMeasure(cubeDesc, newMeasure);
+ getCubeDescManager().updateCubeDesc(updatedCubeDesc);
+ List<MeasureInstance> measuresInsInCube = getMeasureManager().getMeasuresInCube(cubeInstance.getProject(), cubeInstance.getName());
+ List<MeasureDesc> measuresInCube = measuresInsInCube
+ .stream()
+ .map(m -> m.getMeasureDesc())
+ .collect(Collectors.toList());
+ assertTrue(measuresInCube.contains(newMeasure));
+
+ measuresInsInCube.forEach(m -> assertTrue(m.getKey() + " has some segments: " + m.getSegmentsName(), m.getSegments().size() == 0));
+ }
+
+ @Test
+ public void testDeleteMeasureOnNewCube() throws IOException {
+ String newCubeName = "ci_inner_join_cube";
+ CubeInstance cubeInstance = getCubeManager().getCube(newCubeName);
+ CubeDesc cubeDesc = cubeInstance.getDescriptor();
+ MeasureDesc needDeleteMeasure = cubeDesc.getMeasures().get(cubeDesc.getMeasures().size() >> 1);
+ CubeDesc updatedCubeDesc = deleteMeasure(cubeDesc, needDeleteMeasure);
+ getCubeDescManager().updateCubeDesc(updatedCubeDesc);
+ List<MeasureInstance> measuresInsInCube = getMeasureManager().getMeasuresInCube(cubeInstance.getProject(), cubeInstance.getName());
+ List<MeasureDesc> measuresInCube = measuresInsInCube
+ .stream()
+ .map(m -> m.getMeasureDesc())
+ .collect(Collectors.toList());
+ assertTrue(!measuresInCube.contains(needDeleteMeasure));
+ }
+
+
+
+ @Test
+ public void testAddMeasureOnBuiltCube() throws IOException {
+ CubeInstance cubeInstance = getCubeManager().getCube("test_kylin_cube_with_slr_ready_2_segments");
+
+ List<MeasureInstance> measuresInsInCubeBeforeAdd = getMeasureManager().getMeasuresInCube(cubeInstance.getProject(), cubeInstance.getName());
+
+ measuresInsInCubeBeforeAdd.forEach(m -> assertTrue(m.getSegments().size() == cubeInstance.getSegments(SegmentStatusEnum.READY).size()));
+
+ CubeDesc cubeDesc = cubeInstance.getDescriptor();
+ MeasureDesc newMeasure = getMAX_SELLER_ID();
+ CubeDesc updatedCubeDesc = addMeasure(cubeDesc, newMeasure);
+ getCubeDescManager().updateCubeDesc(updatedCubeDesc);
+
+ List<MeasureInstance> measuresInsInCubeAfterAdd = getMeasureManager().getMeasuresInCube(cubeInstance.getProject(), cubeInstance.getName());
+ List<MeasureDesc> measuresInCube = measuresInsInCubeAfterAdd
+ .stream()
+ .map(m -> m.getMeasureDesc())
+ .collect(Collectors.toList());
+ assertTrue(measuresInCube.contains(newMeasure));
+
+ for (MeasureInstance m : measuresInsInCubeAfterAdd) {
+ if (m.getName().equals(newMeasure.getName())) {
+
+ assertTrue(m.getSegments().size() == 0);
+ } else {
+ assertTrue(m.getSegments().size() == cubeInstance.getSegments(SegmentStatusEnum.READY).size());
+ }
+ }
+ }
+
+ @Test
+ public void testGetMeasureAfterDropSegment() throws IOException {
+ getMeasureManager();
+ CubeInstance cubeInstance = getCubeManager().getCube("test_kylin_cube_with_slr_ready_3_segments");
+ CubeSegment firstSegment = cubeInstance.getFirstSegment();
+ CubeInstance cubeAfterDelete = getCubeManager().updateCubeDropSegments(cubeInstance, firstSegment);
+
+ List<MeasureInstance> measuresInCube = getMeasureManager().getMeasuresInCube(cubeInstance.getProject(), cubeInstance.getName());
+ for (MeasureInstance m : measuresInCube) {
+ assertTrue(m.getSegments().size() == cubeAfterDelete.getSegments(SegmentStatusEnum.READY).size());
+ assertTrue(!m.getSegments().contains(firstSegment));
+ }
+ }
+
+ private CubeDescManager getCubeDescManager() {
+ return CubeDescManager.getInstance(getTestConfig());
+ }
+
+ private CubeManager getCubeManager() {
+ return CubeManager.getInstance(getTestConfig());
+ }
+
+ public MeasureDesc getMAX_SELLER_ID() {
+ return parseMeasureData("MAX_SELLER_ID");
+ }
+
+ private MeasureDesc parseMeasureData(String path) {
+ File file = new File(MEASURE_DATA_DIR + path + MEASURE_DATA_SUFFIX);
+ try {
+ return JsonUtil.readValue(file, MeasureDesc.class);
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private CubeDesc addMeasure(CubeDesc cubeDesc, MeasureDesc needAdd) {
+ List<MeasureDesc> measures = Lists.newArrayList(cubeDesc.getMeasures());
+ measures.add(needAdd);
+ cubeDesc.setMeasures(measures);
+ HBaseMappingDesc hBaseMappingDesc = AbstractHBaseMappingAdapter.getHBaseAdapter(getTestConfig()).addMeasure(cubeDesc, Arrays.asList(needAdd.getName()));
+ cubeDesc.setHbaseMapping(hBaseMappingDesc);
+ return cubeDesc;
+ }
+ private CubeDesc deleteMeasure(CubeDesc cubeDesc, MeasureDesc needDeleteMeasure) {
+ List<MeasureDesc> newMeasures = Lists.newArrayList(cubeDesc.getMeasures());
+ newMeasures.remove(needDeleteMeasure);
+ cubeDesc.setMeasures(newMeasures);
+ HBaseMappingDesc hBaseMappingDesc = AbstractHBaseMappingAdapter.getHBaseAdapter(getTestConfig()).getHBaseMappingOnlyOnce(cubeDesc);
+ cubeDesc.setHbaseMapping(hBaseMappingDesc);
+ return cubeDesc;
+ }
+ private MeasureManager getMeasureManager() {
+ return MeasureManager.getInstance(getTestConfig());
+ }
+}
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DateTimeRange.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DateTimeRange.java
new file mode 100644
index 0000000..ac80454
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DateTimeRange.java
@@ -0,0 +1,46 @@
+/*
+ * 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.metadata.model;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+public class DateTimeRange extends SegmentRange<LocalDateTime> {
+
+ public static DateTimeRange create(long s, long e) {
+ return new DateTimeRange(getDateTimeOfTimestamp(s), getDateTimeOfTimestamp(e));
+ }
+
+ public DateTimeRange(LocalDateTime start, LocalDateTime end) {
+ super(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return "[" + this.start.v.toString() + ", " + this.end.v.toString() + ")";
+ }
+
+
+ public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
+ Instant instant = Instant.ofEpochMilli(timestamp);
+ ZoneId zone = ZoneId.of("GMT");
+ return LocalDateTime.ofInstant(instant, zone);
+ }
+}
diff --git a/examples/sample_cube/template/measure/kylin_sales_cube/BUYER_LEVEL_SUM.json b/examples/sample_cube/template/measure/kylin_sales_cube/BUYER_LEVEL_SUM.json
new file mode 100644
index 0000000..c04c7d9
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_sales_cube/BUYER_LEVEL_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4f099a83-1e14-702a-3756-cbab09740bd6",
+ "last_modified" : 1557191165660,
+ "version" : "2.6.0.20500",
+ "name" : "BUYER_LEVEL_SUM",
+ "cube_name" : "kylin_sales_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_sales_cube/GMV_SUM.json b/examples/sample_cube/template/measure/kylin_sales_cube/GMV_SUM.json
new file mode 100644
index 0000000..7ba763f
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_sales_cube/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "16490392-e3c9-5ea6-cddd-057e4ab15f9d",
+ "last_modified" : 1557191165614,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "kylin_sales_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_sales_cube/SELLER_CNT_HLL.json b/examples/sample_cube/template/measure/kylin_sales_cube/SELLER_CNT_HLL.json
new file mode 100644
index 0000000..f74d9be
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_sales_cube/SELLER_CNT_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "801ef9c6-4638-bde7-0859-804e1438611c",
+ "last_modified" : 1557191165670,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CNT_HLL",
+ "cube_name" : "kylin_sales_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_sales_cube/SELLER_LEVEL_SUM.json b/examples/sample_cube/template/measure/kylin_sales_cube/SELLER_LEVEL_SUM.json
new file mode 100644
index 0000000..7bb12ac
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_sales_cube/SELLER_LEVEL_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "bbd71a34-ccdd-1cc8-4d0e-770830a48e6d",
+ "last_modified" : 1557191165663,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_LEVEL_SUM",
+ "cube_name" : "kylin_sales_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_sales_cube/TOP_SELLER.json b/examples/sample_cube/template/measure/kylin_sales_cube/TOP_SELLER.json
new file mode 100644
index 0000000..03507b5
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_sales_cube/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "14204832-c61f-aa22-43c7-5212b90dbd06",
+ "last_modified" : 1557191165673,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "kylin_sales_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_sales_cube/TRANS_CNT.json b/examples/sample_cube/template/measure/kylin_sales_cube/TRANS_CNT.json
new file mode 100644
index 0000000..9af7ba0
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_sales_cube/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5c2759c1-128c-7c27-c36b-4826a459ab04",
+ "last_modified" : 1557191165667,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "kylin_sales_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_streaming_cube/TOTAL_AMOUNT.json b/examples/sample_cube/template/measure/kylin_streaming_cube/TOTAL_AMOUNT.json
new file mode 100644
index 0000000..ba8a751
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_streaming_cube/TOTAL_AMOUNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c804c0e9-d1c5-c677-e324-bc4d1fbba074",
+ "last_modified" : 1557191165679,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_AMOUNT",
+ "cube_name" : "kylin_streaming_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_streaming_cube/TOTAL_QTY.json b/examples/sample_cube/template/measure/kylin_streaming_cube/TOTAL_QTY.json
new file mode 100644
index 0000000..f93ff8e
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_streaming_cube/TOTAL_QTY.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "849e959f-437b-c717-b159-d5df97ecb354",
+ "last_modified" : 1557191165682,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_QTY",
+ "cube_name" : "kylin_streaming_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/sample_cube/template/measure/kylin_streaming_cube/_COUNT_.json b/examples/sample_cube/template/measure/kylin_streaming_cube/_COUNT_.json
new file mode 100644
index 0000000..20b5b13
--- /dev/null
+++ b/examples/sample_cube/template/measure/kylin_streaming_cube/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d1538137-528f-c7e7-5038-fca89dd0f268",
+ "last_modified" : 1557191165676,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "kylin_streaming_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/BUYER_CONTACT.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/BUYER_CONTACT.json
new file mode 100644
index 0000000..9fee10d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/BUYER_CONTACT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "21ed4daf-6bd6-f49c-4e14-a0e92849128e",
+ "last_modified" : 1556584529151,
+ "version" : "2.6.0.20500",
+ "name" : "BUYER_CONTACT",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/CAL_DT_RAW.json
new file mode 100644
index 0000000..5eb1fdd
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "de1be29e-58d1-f840-3aff-f75496c74e86",
+ "last_modified" : 1556584529163,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_CNT.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_CNT.json
new file mode 100644
index 0000000..16d883a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "68425d58-a998-ae29-e9be-e477b02d6304",
+ "last_modified" : 1556584529127,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_CNT",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_MAX.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_MAX.json
new file mode 100644
index 0000000..4bb5333
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "04deb300-6356-aaf4-f9e4-6d9a44837a54",
+ "last_modified" : 1556584529134,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_MIN.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_MIN.json
new file mode 100644
index 0000000..7eafc62
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c61ea582-0a33-77b8-35e0-cdefdec3b628",
+ "last_modified" : 1556584529130,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_SUM.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_SUM.json
new file mode 100644
index 0000000..babf89f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9975eb29-5e44-2f63-295e-915ab8f6c959",
+ "last_modified" : 1556584529124,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..7a80c80
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "91f1823c-2811-03a5-2538-632c2f0fd359",
+ "last_modified" : 1556584529121,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/PRICE_RAW.json
new file mode 100644
index 0000000..da83461
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "85ec8895-5116-d0aa-aadb-d4134cb864ef",
+ "last_modified" : 1556584529160,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_CONTACT.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_CONTACT.json
new file mode 100644
index 0000000..9972df0
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_CONTACT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "728fac74-796a-617b-3e02-7225d26ee260",
+ "last_modified" : 1556584529154,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CONTACT",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_FORMAT_HLL.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_FORMAT_HLL.json
new file mode 100644
index 0000000..cb72ad7
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_FORMAT_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "26142ef0-72b2-7566-9704-67dd05c33e78",
+ "last_modified" : 1556584529140,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_FORMAT_HLL",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_HLL.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_HLL.json
new file mode 100644
index 0000000..e75b5a2
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/SELLER_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "68829a34-9a79-9c3a-5bcc-6c87a4b6f987",
+ "last_modified" : 1556584529137,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_HLL",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_COUNT_COLUMN_CNT.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_COUNT_COLUMN_CNT.json
new file mode 100644
index 0000000..b5384aa
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_COUNT_COLUMN_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5ba87fd0-0584-e754-c1c6-63ef37e45b5a",
+ "last_modified" : 1556584529166,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_COUNT_COLUMN_CNT",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_COUNT_DISTINCT_BITMAP.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_COUNT_DISTINCT_BITMAP.json
new file mode 100644
index 0000000..d08bd06
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_COUNT_DISTINCT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "05133092-a741-6727-d39a-8e516b1d18a2",
+ "last_modified" : 1556584529145,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_COUNT_DISTINCT_BITMAP",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_EXTENDED_COLUMN.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_EXTENDED_COLUMN.json
new file mode 100644
index 0000000..dede53d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TEST_EXTENDED_COLUMN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4728882d-5def-9245-7906-a3f32c67f1a0",
+ "last_modified" : 1556584529149,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_EXTENDED_COLUMN",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TOP_SELLER.json
new file mode 100644
index 0000000..da65103
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "859659a1-706a-006a-e5e3-b4807341a883",
+ "last_modified" : 1556584529142,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TRANS_CNT.json
new file mode 100644
index 0000000..27c28d5
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "fc662172-4939-f075-c712-04b8ddebe366",
+ "last_modified" : 1556584529083,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TRANS_ID_RAW.json b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TRANS_ID_RAW.json
new file mode 100644
index 0000000..bd841ba
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_inner_join_cube/TRANS_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "3bf11317-348b-59ab-61bb-ba887a841ee8",
+ "last_modified" : 1556584529157,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_ID_RAW",
+ "cube_name" : "ci_inner_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/BUYER_CONTACT.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/BUYER_CONTACT.json
new file mode 100644
index 0000000..370e2ab
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/BUYER_CONTACT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "92da77d8-ff90-c328-7617-6d812391b3ec",
+ "last_modified" : 1556584529202,
+ "version" : "2.6.0.20500",
+ "name" : "BUYER_CONTACT",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/CAL_DT_RAW.json
new file mode 100644
index 0000000..5e14386
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b810c89f-a494-74f0-fdb6-fb3c7bae9d88",
+ "last_modified" : 1556584529213,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_CNT.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_CNT.json
new file mode 100644
index 0000000..0235f18
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "238e8d62-fed2-0f28-b059-d7ae49e29f29",
+ "last_modified" : 1556584529178,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_CNT",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_MAX.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_MAX.json
new file mode 100644
index 0000000..06ee157
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "6d4981d1-78d1-ed88-4bee-984cc6194b6c",
+ "last_modified" : 1556584529184,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_MIN.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_MIN.json
new file mode 100644
index 0000000..416657a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f6fc1c8b-cbb5-2b30-39c8-e3a504ef5dfc",
+ "last_modified" : 1556584529181,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_SUM.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_SUM.json
new file mode 100644
index 0000000..328cfa2
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "94f5e426-9f6c-0fd4-fc63-cb0bc560c1e8",
+ "last_modified" : 1556584529175,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/GVM_PERCENTILE.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GVM_PERCENTILE.json
new file mode 100644
index 0000000..d3dddc2
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/GVM_PERCENTILE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f3206098-1a23-bb7a-e129-e4c7074a9900",
+ "last_modified" : 1556584529216,
+ "version" : "2.6.0.20500",
+ "name" : "GVM_PERCENTILE",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..6947271
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0957c61f-e1e8-bbc0-dadc-8b9f191bb140",
+ "last_modified" : 1556584529172,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/PRICE_RAW.json
new file mode 100644
index 0000000..7c78b8f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d300ebdb-c9da-b0a5-d900-cca205cfd134",
+ "last_modified" : 1556584529210,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_CONTACT.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_CONTACT.json
new file mode 100644
index 0000000..d6e60ed
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_CONTACT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "1c8e1ebd-855b-8d5e-1b60-6da269e11605",
+ "last_modified" : 1556584529204,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CONTACT",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_FORMAT_HLL.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_FORMAT_HLL.json
new file mode 100644
index 0000000..c4c99f8
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_FORMAT_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "de21a5a6-5029-4fbb-81e5-cb77a9452806",
+ "last_modified" : 1556584529190,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_FORMAT_HLL",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_HLL.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_HLL.json
new file mode 100644
index 0000000..1108370
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/SELLER_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "1a1ecc38-451b-464f-b54b-5d989b4d469d",
+ "last_modified" : 1556584529187,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_HLL",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_COUNT_COLUMN_CNT.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_COUNT_COLUMN_CNT.json
new file mode 100644
index 0000000..6b46bf9
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_COUNT_COLUMN_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4942846c-38e3-d5fe-90a7-95e9234f3d83",
+ "last_modified" : 1556584529219,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_COUNT_COLUMN_CNT",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_COUNT_DISTINCT_BITMAP.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_COUNT_DISTINCT_BITMAP.json
new file mode 100644
index 0000000..b6b4bd3
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_COUNT_DISTINCT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "bfdaf4cb-8e4d-662f-c44e-d1be13156b6a",
+ "last_modified" : 1556584529196,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_COUNT_DISTINCT_BITMAP",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_EXTENDED_COLUMN.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_EXTENDED_COLUMN.json
new file mode 100644
index 0000000..5888a75
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TEST_EXTENDED_COLUMN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9cd64950-ffb2-e8bd-e464-6a024eda2901",
+ "last_modified" : 1556584529199,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_EXTENDED_COLUMN",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TOP_SELLER.json
new file mode 100644
index 0000000..7c269de
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "2b7fc8f4-e1c1-32c4-7872-160fd1ec6ecf",
+ "last_modified" : 1556584529193,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TRANS_CNT.json
new file mode 100644
index 0000000..347d1a6
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "3c4c8c88-6bea-e439-41f4-b7a77927da4d",
+ "last_modified" : 1556584529169,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ci_left_join_cube/TRANS_ID_RAW.json b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TRANS_ID_RAW.json
new file mode 100644
index 0000000..ae92725
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ci_left_join_cube/TRANS_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9c18b16f-22ce-6eab-24aa-d211e94c4aea",
+ "last_modified" : 1556584529207,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_ID_RAW",
+ "cube_name" : "ci_left_join_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/fifty_dim_full_build_cube/_COUNT_.json b/examples/test_case_data/localmeta/measure/fifty_dim_full_build_cube/_COUNT_.json
new file mode 100644
index 0000000..2f2bc67
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/fifty_dim_full_build_cube/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "25baa916-2287-0d36-4938-0d75094ebbda",
+ "last_modified" : 1556584529222,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "fifty_dim_full_build_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb/TOTAL_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb/TOTAL_REVENUE.json
new file mode 100644
index 0000000..ef68e51
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb/TOTAL_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f925a53e-da71-a9ae-3866-1fc296462e47",
+ "last_modified" : 1556584529229,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_REVENUE",
+ "cube_name" : "ssb",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb/TOTAL_SUPPLYCOST.json b/examples/test_case_data/localmeta/measure/ssb/TOTAL_SUPPLYCOST.json
new file mode 100644
index 0000000..e4ac5fa
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb/TOTAL_SUPPLYCOST.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "57d3ee89-c95c-f846-1c88-8a3a876cfea7",
+ "last_modified" : 1556584529232,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_SUPPLYCOST",
+ "cube_name" : "ssb",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb/TOTAL_V_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb/TOTAL_V_REVENUE.json
new file mode 100644
index 0000000..73c7413
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb/TOTAL_V_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "abf3238c-1184-24b5-6525-732c9174786f",
+ "last_modified" : 1556584529234,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_V_REVENUE",
+ "cube_name" : "ssb",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb/_COUNT_.json b/examples/test_case_data/localmeta/measure/ssb/_COUNT_.json
new file mode 100644
index 0000000..2164636
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b0831650-9e56-95f7-1b9a-105ea4260038",
+ "last_modified" : 1556584529225,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "ssb",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_REVENUE.json
new file mode 100644
index 0000000..26c4f60
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "ca1622f8-046b-b1c1-d8e1-08206d25c7bc",
+ "last_modified" : 1556584529241,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_REVENUE",
+ "cube_name" : "ssb_cube1",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_SUPPLYCOST.json b/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_SUPPLYCOST.json
new file mode 100644
index 0000000..b92b250
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_SUPPLYCOST.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "43999d14-59d2-4288-d7cf-b78eb59b9544",
+ "last_modified" : 1556584529244,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_SUPPLYCOST",
+ "cube_name" : "ssb_cube1",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_V_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_V_REVENUE.json
new file mode 100644
index 0000000..b30b57a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube1/TOTAL_V_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "ac78157d-bd86-2476-42d2-712d2ac4acd0",
+ "last_modified" : 1556584529247,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_V_REVENUE",
+ "cube_name" : "ssb_cube1",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube1/_COUNT_.json b/examples/test_case_data/localmeta/measure/ssb_cube1/_COUNT_.json
new file mode 100644
index 0000000..154a8e3
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube1/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "182cdf1d-a95b-9945-1ee2-becdf8352a86",
+ "last_modified" : 1556584529237,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "ssb_cube1",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_REVENUE.json
new file mode 100644
index 0000000..3383433
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "63b33a86-8b02-dc3c-5a93-d91442d1e400",
+ "last_modified" : 1556584529253,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_REVENUE",
+ "cube_name" : "ssb_cube2",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_SUPPLYCOST.json b/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_SUPPLYCOST.json
new file mode 100644
index 0000000..ac1b771
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_SUPPLYCOST.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "e2e3f914-3970-b5d0-3503-44b4f4942e9f",
+ "last_modified" : 1556584529256,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_SUPPLYCOST",
+ "cube_name" : "ssb_cube2",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_V_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_V_REVENUE.json
new file mode 100644
index 0000000..dd563e9
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube2/TOTAL_V_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0e82b772-a18e-f4b0-2360-97830dff74ba",
+ "last_modified" : 1556584529259,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_V_REVENUE",
+ "cube_name" : "ssb_cube2",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube2/_COUNT_.json b/examples/test_case_data/localmeta/measure/ssb_cube2/_COUNT_.json
new file mode 100644
index 0000000..c7e689b
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube2/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "89e50c9d-d6a0-f45a-8161-e097a7865c02",
+ "last_modified" : 1556584529250,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "ssb_cube2",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube3/TOTAL_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb_cube3/TOTAL_REVENUE.json
new file mode 100644
index 0000000..0d2d992
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube3/TOTAL_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a1d86904-9382-c16b-7b23-d11d339012cd",
+ "last_modified" : 1556584529265,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_REVENUE",
+ "cube_name" : "ssb_cube3",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube3/TOTAL_SUPPLYCOST.json b/examples/test_case_data/localmeta/measure/ssb_cube3/TOTAL_SUPPLYCOST.json
new file mode 100644
index 0000000..df2415c
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube3/TOTAL_SUPPLYCOST.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d1198145-36b1-b18d-08d9-eebeaf0dac13",
+ "last_modified" : 1556584529268,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_SUPPLYCOST",
+ "cube_name" : "ssb_cube3",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube3/_COUNT_.json b/examples/test_case_data/localmeta/measure/ssb_cube3/_COUNT_.json
new file mode 100644
index 0000000..eeca378
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube3/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "fd30eda2-8207-1fe0-81b3-98c223e89449",
+ "last_modified" : 1556584529262,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "ssb_cube3",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/TOTAL_REVENUE.json b/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/TOTAL_REVENUE.json
new file mode 100644
index 0000000..d73492c
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/TOTAL_REVENUE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "558ecc93-e1e3-4f67-ae2c-39e5deffeed0",
+ "last_modified" : 1556584529290,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_REVENUE",
+ "cube_name" : "ssb_cube_with_dimention_range",
+ "segments_name" : [ "19920523163722_20180523173026" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/TOTAL_SUPPLYCOST.json b/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/TOTAL_SUPPLYCOST.json
new file mode 100644
index 0000000..c2ec700
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/TOTAL_SUPPLYCOST.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7acbd8b0-0b73-5ad1-ad43-50b401f2d65e",
+ "last_modified" : 1556584529293,
+ "version" : "2.6.0.20500",
+ "name" : "TOTAL_SUPPLYCOST",
+ "cube_name" : "ssb_cube_with_dimention_range",
+ "segments_name" : [ "19920523163722_20180523173026" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/_COUNT_.json b/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/_COUNT_.json
new file mode 100644
index 0000000..b6643bc
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/ssb_cube_with_dimention_range/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4d2e4f04-fb94-e06f-2f9a-2cd47fb0bee2",
+ "last_modified" : 1556584529286,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "ssb_cube_with_dimention_range",
+ "segments_name" : [ "19920523163722_20180523173026" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_MAX.json
new file mode 100644
index 0000000..6d41954
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "27217dee-62b2-18d3-fd08-3ab21014ebe9",
+ "last_modified" : 1556584529302,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_1_new_segment",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_MIN.json
new file mode 100644
index 0000000..cd1d066
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b25cd796-67e7-29b2-d99e-4429b5ce5881",
+ "last_modified" : 1556584529299,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_1_new_segment",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_SUM.json
new file mode 100644
index 0000000..a390281
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b7d6eadb-1ac5-58f1-d754-1f6499c8376e",
+ "last_modified" : 1556584529296,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_1_new_segment",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..ed50245
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0a7a1c58-8261-bec2-d036-723cb98f1731",
+ "last_modified" : 1556584529308,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_1_new_segment",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/TRANS_CNT.json
new file mode 100644
index 0000000..e8d650d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_1_new_segment/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "2c535460-388d-2bb4-66dd-35c0aff101d5",
+ "last_modified" : 1556584529305,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_1_new_segment",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_MAX.json
new file mode 100644
index 0000000..c7e5b89
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "2f5386dd-59ef-213d-6118-2cfb49e9567c",
+ "last_modified" : 1556584529317,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_MIN.json
new file mode 100644
index 0000000..523a557
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7fdff937-8311-1bc9-adf5-00c36ee358f0",
+ "last_modified" : 1556584529314,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_SUM.json
new file mode 100644
index 0000000..3c65992
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "29eb0927-5c91-8605-58d7-f3e5e31c158e",
+ "last_modified" : 1556584529310,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..efc985d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "1b37e35d-8504-1f0f-e5b5-4ac6edf8fb7f",
+ "last_modified" : 1556584529322,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/TRANS_CNT.json
new file mode 100644
index 0000000..a2e1ed8
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_empty/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "8356ff44-a4c1-2366-6dae-0f1f6425c54f",
+ "last_modified" : 1556584529320,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_MAX.json
new file mode 100644
index 0000000..1c8388a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "ed13d130-6bd7-605c-c31b-f71c47325fca",
+ "last_modified" : 1556584529331,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_MIN.json
new file mode 100644
index 0000000..7a9f14e
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "8bf0a134-802d-2a92-c332-205a098fc251",
+ "last_modified" : 1556584529329,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_SUM.json
new file mode 100644
index 0000000..017923f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "1f411a72-4601-f82f-f68f-97c885f3e467",
+ "last_modified" : 1556584529325,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..7cbda46
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "91d44cec-11e2-0b78-7b20-fc853d542a6b",
+ "last_modified" : 1556584529337,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/SELLER_CNT_HLL.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/SELLER_CNT_HLL.json
new file mode 100644
index 0000000..a31400d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/SELLER_CNT_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9febbd32-8ef7-4582-9d6f-02dfd130e35a",
+ "last_modified" : 1556584529340,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CNT_HLL",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/TOP_SELLER.json
new file mode 100644
index 0000000..8c1a17b
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "60dc5b5f-0b38-ebe6-dab6-3cb240b6f2a0",
+ "last_modified" : 1556584529343,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/TRANS_CNT.json
new file mode 100644
index 0000000..92e0ae2
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_empty/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c47a5b8b-899a-9f8d-c946-aadb2d250057",
+ "last_modified" : 1556584529334,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_MAX.json
new file mode 100644
index 0000000..4864f55
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "55886eab-e710-86c8-25b6-04f81f6593f7",
+ "last_modified" : 1556584529353,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_MIN.json
new file mode 100644
index 0000000..d2a5121
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "24a6c675-b5f0-2df3-86d8-a02864e3f91c",
+ "last_modified" : 1556584529350,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_SUM.json
new file mode 100644
index 0000000..cf94581
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "bdee8d95-b41e-4fea-50e4-0ceee365abc5",
+ "last_modified" : 1556584529346,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..2386743
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b370245a-680c-19d5-b9df-5871bdada3b5",
+ "last_modified" : 1556584529359,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/SELLER_CNT_HLL.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/SELLER_CNT_HLL.json
new file mode 100644
index 0000000..4ba5320
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/SELLER_CNT_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "45e8100c-ac2e-d3ee-3115-cfd1d195561a",
+ "last_modified" : 1556584529361,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CNT_HLL",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/TOP_SELLER.json
new file mode 100644
index 0000000..a1daafe
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f0cbdd45-544a-8244-06ba-fda9b5350027",
+ "last_modified" : 1556584529364,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/TRANS_CNT.json
new file mode 100644
index 0000000..4d78406
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_left_join_ready/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "81a0ef0f-02ee-9498-e69e-7e7aaf95f5e3",
+ "last_modified" : 1556584529356,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_left_join_ready",
+ "segments_name" : [ "1eaca32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_MAX.json
new file mode 100644
index 0000000..92d6e22
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9354668b-57d5-fc1c-6f8e-82915ce25cf8",
+ "last_modified" : 1556584529373,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_ready",
+ "segments_name" : [ "20130331080000_20131212080000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_MIN.json
new file mode 100644
index 0000000..2a9650a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f2d73907-61c4-cab8-36a4-2f9987112cb0",
+ "last_modified" : 1556584529371,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_ready",
+ "segments_name" : [ "20130331080000_20131212080000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_SUM.json
new file mode 100644
index 0000000..73ffb4f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b9c5d764-2197-6c51-9bc0-0f65383b976c",
+ "last_modified" : 1556584529367,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_ready",
+ "segments_name" : [ "20130331080000_20131212080000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..708fc0d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "90dec7a9-966e-9a50-c587-434b181795ad",
+ "last_modified" : 1556584529379,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_ready",
+ "segments_name" : [ "20130331080000_20131212080000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/TRANS_CNT.json
new file mode 100644
index 0000000..e50098f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "adcfd0fa-850e-2714-21fd-ca85484dbbfe",
+ "last_modified" : 1556584529376,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_ready",
+ "segments_name" : [ "20130331080000_20131212080000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_MAX.json
new file mode 100644
index 0000000..cd2bb45
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "3eaa2a6c-153c-0319-8ea3-2e5996cd8f0e",
+ "last_modified" : 1556584529388,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_MIN.json
new file mode 100644
index 0000000..66939c7
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "2cc0154f-270a-b838-ace8-5ec4e721d768",
+ "last_modified" : 1556584529385,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_SUM.json
new file mode 100644
index 0000000..a593ff9
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "bee141fa-4860-8975-7397-72f29f16b5b2",
+ "last_modified" : 1556584529382,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..5e97979
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b786963b-3774-3b0b-3f15-fc131df55a2c",
+ "last_modified" : 1556584529394,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/TRANS_CNT.json
new file mode 100644
index 0000000..8188982
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_2_segments/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "56a2de0f-1f19-d898-9eb1-53ad4a7404c7",
+ "last_modified" : 1556584529391,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_MAX.json
new file mode 100644
index 0000000..60e8459
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "caa210a4-1ab0-e3fb-4605-b50e2a05d566",
+ "last_modified" : 1556584529403,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_with_slr_ready_3_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_MIN.json
new file mode 100644
index 0000000..736ea08
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "85973492-bcf2-cc86-efd0-b8b208201ccf",
+ "last_modified" : 1556584529400,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_with_slr_ready_3_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_SUM.json
new file mode 100644
index 0000000..3cc7f2c
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "31655f53-c5f7-e276-5d07-4bf96b88c263",
+ "last_modified" : 1556584529397,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_ready_3_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..cd64ea5
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c3009871-15fb-27ef-b1d1-955be0f15781",
+ "last_modified" : 1556584529409,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_with_slr_ready_3_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/TRANS_CNT.json
new file mode 100644
index 0000000..878203d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_with_slr_ready_3_segments/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "43766b32-114b-5a33-4088-1d1f7684a26d",
+ "last_modified" : 1556584529406,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_with_slr_ready_3_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/CAL_DT_RAW.json
new file mode 100644
index 0000000..b37a104
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5f13b694-ca25-6815-604a-d28750b7e947",
+ "last_modified" : 1556584529431,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_MAX.json
new file mode 100644
index 0000000..61717d7
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "caa4fd81-b2cd-acd6-56e4-18a24d9e2b7a",
+ "last_modified" : 1556584529417,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_MIN.json
new file mode 100644
index 0000000..00e2d96
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d9288ca0-95a7-503e-9e04-ce0881e362ce",
+ "last_modified" : 1556584529415,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_SUM.json
new file mode 100644
index 0000000..4e127ef
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f3c0b2eb-e370-d841-609a-24eb781421de",
+ "last_modified" : 1556584529411,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..5838c15
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "879fd068-97ac-411c-874e-9f0871cd6093",
+ "last_modified" : 1556584529423,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/LEAF_CATEG_ID_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/LEAF_CATEG_ID_RAW.json
new file mode 100644
index 0000000..40fc8ba
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/LEAF_CATEG_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a7425727-cc16-862b-9252-d809304fb095",
+ "last_modified" : 1556584529437,
+ "version" : "2.6.0.20500",
+ "name" : "LEAF_CATEG_ID_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/LSTG_FORMAT_NAME_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/LSTG_FORMAT_NAME_RAW.json
new file mode 100644
index 0000000..2f42ae4
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/LSTG_FORMAT_NAME_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "75fb4890-c688-bab0-483b-ae43c3e96fe0",
+ "last_modified" : 1556584529434,
+ "version" : "2.6.0.20500",
+ "name" : "LSTG_FORMAT_NAME_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/PRICE_RAW.json
new file mode 100644
index 0000000..6bae11d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5bd4e9b7-bb1d-c98c-b7d8-b1c52e6d9806",
+ "last_modified" : 1556584529439,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/SITE_EXTENDED_1.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/SITE_EXTENDED_1.json
new file mode 100644
index 0000000..ded7286
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/SITE_EXTENDED_1.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "ef5aebba-f293-8c65-8139-29333c17f183",
+ "last_modified" : 1556584529426,
+ "version" : "2.6.0.20500",
+ "name" : "SITE_EXTENDED_1",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/SITE_EXTENDED_2.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/SITE_EXTENDED_2.json
new file mode 100644
index 0000000..2882eb4
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/SITE_EXTENDED_2.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9cfbdd03-315c-6fe3-2150-4460dafc5cc9",
+ "last_modified" : 1556584529428,
+ "version" : "2.6.0.20500",
+ "name" : "SITE_EXTENDED_2",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/TRANS_CNT.json
new file mode 100644
index 0000000..de2b400
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_empty/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "caf46641-b6ed-0b7d-c3af-29abffcdc2c0",
+ "last_modified" : 1556584529420,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/CAL_DT_RAW.json
new file mode 100644
index 0000000..dc5baab
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a05eba7a-5cd1-af83-7e90-092241752532",
+ "last_modified" : 1556584529469,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_MAX.json
new file mode 100644
index 0000000..8c3096a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "8e8117f7-5f84-ad42-ee99-20cf63b82726",
+ "last_modified" : 1556584529449,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_MIN.json
new file mode 100644
index 0000000..8578837
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "26c85e51-2264-73d2-241f-211e6a6578c8",
+ "last_modified" : 1556584529446,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_SUM.json
new file mode 100644
index 0000000..56be699
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "63e1c52e-4b7b-76d9-d88d-597b310b35c8",
+ "last_modified" : 1556584529442,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..782f05e
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9d5386da-4c3a-31eb-28a9-71c27803c658",
+ "last_modified" : 1556584529454,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/LEAF_CATEG_ID_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/LEAF_CATEG_ID_RAW.json
new file mode 100644
index 0000000..829b6da
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/LEAF_CATEG_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "36ece6c6-71e8-0422-b087-bd0056989dc4",
+ "last_modified" : 1556584529474,
+ "version" : "2.6.0.20500",
+ "name" : "LEAF_CATEG_ID_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/LSTG_FORMAT_NAME_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/LSTG_FORMAT_NAME_RAW.json
new file mode 100644
index 0000000..b98f723
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/LSTG_FORMAT_NAME_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f8dd7d77-97d4-9478-5b5f-1823d56888d3",
+ "last_modified" : 1556584529471,
+ "version" : "2.6.0.20500",
+ "name" : "LSTG_FORMAT_NAME_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/PRICE_RAW.json
new file mode 100644
index 0000000..f8d7dc0
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9ed21d54-9294-476b-1f4b-272bf6b7e44c",
+ "last_modified" : 1556584529477,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/SELLER_CNT_BITMAP.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/SELLER_CNT_BITMAP.json
new file mode 100644
index 0000000..a010e16
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/SELLER_CNT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7cdc1c1d-9cd2-30bd-1679-0e27c383c764",
+ "last_modified" : 1556584529457,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CNT_BITMAP",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/SELLER_FORMAT_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/SELLER_FORMAT_CNT.json
new file mode 100644
index 0000000..e74f46e
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/SELLER_FORMAT_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "20ac5007-2cb6-fe5e-9fa4-be719d3d55e3",
+ "last_modified" : 1556584529463,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_FORMAT_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/TOP_SELLER.json
new file mode 100644
index 0000000..63c8cd8
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d53f1971-95c6-2bc6-bec1-42dcfc443843",
+ "last_modified" : 1556584529466,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/TRANS_CNT.json
new file mode 100644
index 0000000..f721b10
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f36f3ff5-8c9f-3226-42b8-b752e35b6332",
+ "last_modified" : 1556584529452,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/USER_COUNT_BITMAP.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/USER_COUNT_BITMAP.json
new file mode 100644
index 0000000..d34ad29
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_empty/USER_COUNT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "e75bbe76-202f-3984-41be-45b18c32b471",
+ "last_modified" : 1556584529460,
+ "version" : "2.6.0.20500",
+ "name" : "USER_COUNT_BITMAP",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_empty",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/CAL_DT_RAW.json
new file mode 100644
index 0000000..028cf06
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c32b5fe7-b588-863a-f482-e28dbba29aca",
+ "last_modified" : 1556584529506,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_MAX.json
new file mode 100644
index 0000000..d96ac4a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5da0a571-2521-3361-5f4b-0e53d5c3f464",
+ "last_modified" : 1556584529487,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_MIN.json
new file mode 100644
index 0000000..7f5bb83
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "8c422002-a7a3-fad3-e7f1-7384a12afac5",
+ "last_modified" : 1556584529484,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_SUM.json
new file mode 100644
index 0000000..6140f07
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5ed73b4a-94bb-8ec2-23dd-b36028b57ede",
+ "last_modified" : 1556584529481,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..3a4e852
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4c4f7090-bb12-d421-9276-6504fc2319b5",
+ "last_modified" : 1556584529493,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/LEAF_CATEG_ID_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/LEAF_CATEG_ID_RAW.json
new file mode 100644
index 0000000..09fd747
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/LEAF_CATEG_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d7c59527-f762-43e8-644e-f37fa02d2b5f",
+ "last_modified" : 1556584529512,
+ "version" : "2.6.0.20500",
+ "name" : "LEAF_CATEG_ID_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/LSTG_FORMAT_NAME_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/LSTG_FORMAT_NAME_RAW.json
new file mode 100644
index 0000000..5c8e79e
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/LSTG_FORMAT_NAME_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "3632fc8c-be1a-e8ea-3049-214a62371204",
+ "last_modified" : 1556584529509,
+ "version" : "2.6.0.20500",
+ "name" : "LSTG_FORMAT_NAME_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/PRICE_RAW.json
new file mode 100644
index 0000000..78c2883
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "35d9f2df-6e1f-23f7-bb54-1b50453b02be",
+ "last_modified" : 1556584529515,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/SELLER_CNT_BITMAP.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/SELLER_CNT_BITMAP.json
new file mode 100644
index 0000000..6fcd298
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/SELLER_CNT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0c3a35fb-10bc-5735-f395-42f0a6b2a9cb",
+ "last_modified" : 1556584529495,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CNT_BITMAP",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/SELLER_FORMAT_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/SELLER_FORMAT_CNT.json
new file mode 100644
index 0000000..798a151
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/SELLER_FORMAT_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f7407156-e4e4-5b63-e1e1-5e48fd94d643",
+ "last_modified" : 1556584529501,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_FORMAT_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/TOP_SELLER.json
new file mode 100644
index 0000000..486d02a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4975c9ad-4292-6354-2e6b-6cb5fd73c4eb",
+ "last_modified" : 1556584529504,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/TRANS_CNT.json
new file mode 100644
index 0000000..977a751
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "8228b2c3-0764-4431-48d7-e6bbfd4a6ba4",
+ "last_modified" : 1556584529490,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/USER_COUNT_BITMAP.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/USER_COUNT_BITMAP.json
new file mode 100644
index 0000000..e85bf0d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready/USER_COUNT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d7d39502-be4e-7b3b-2fec-20f76e8af369",
+ "last_modified" : 1556584529498,
+ "version" : "2.6.0.20500",
+ "name" : "USER_COUNT_BITMAP",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready",
+ "segments_name" : [ "2accs32a-a33e-4b69-83dd-xxe8b1f8dddd" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/CAL_DT_RAW.json
new file mode 100644
index 0000000..fa58122
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f6eeeab7-cb6a-1aba-b315-20b2002c9966",
+ "last_modified" : 1556584529543,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_MAX.json
new file mode 100644
index 0000000..8915593
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "b766222e-9717-65ec-63c4-378149053879",
+ "last_modified" : 1556584529524,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_MIN.json
new file mode 100644
index 0000000..ba3120b
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "91b7bf0a-f8e1-0ca1-93e1-b166a1b2e68b",
+ "last_modified" : 1556584529521,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_SUM.json
new file mode 100644
index 0000000..08b0dd7
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9c2e4e52-3e3a-e9de-1f21-986983d63e7e",
+ "last_modified" : 1556584529518,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..9d7899d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0a5e6660-646d-ea92-bde9-8f8c8031e00c",
+ "last_modified" : 1556584529529,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/LEAF_CATEG_ID_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/LEAF_CATEG_ID_RAW.json
new file mode 100644
index 0000000..efe604d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/LEAF_CATEG_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "5dc68682-7838-194d-10ec-c223c6ca71fb",
+ "last_modified" : 1556584529548,
+ "version" : "2.6.0.20500",
+ "name" : "LEAF_CATEG_ID_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/LSTG_FORMAT_NAME_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/LSTG_FORMAT_NAME_RAW.json
new file mode 100644
index 0000000..026b5c3
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/LSTG_FORMAT_NAME_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "3944977e-7271-b57a-8d7b-ba77d04a9be8",
+ "last_modified" : 1556584529546,
+ "version" : "2.6.0.20500",
+ "name" : "LSTG_FORMAT_NAME_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/PRICE_RAW.json
new file mode 100644
index 0000000..af4b8e7
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7a74abbe-7bfb-93d2-4ec5-d2152a3958e3",
+ "last_modified" : 1556584529551,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/SELLER_CNT_BITMAP.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/SELLER_CNT_BITMAP.json
new file mode 100644
index 0000000..6658107
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/SELLER_CNT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "dbf378e6-810b-f11d-0b96-56e9613a4d4b",
+ "last_modified" : 1556584529532,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CNT_BITMAP",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/SELLER_FORMAT_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/SELLER_FORMAT_CNT.json
new file mode 100644
index 0000000..cf54e14
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/SELLER_FORMAT_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "410c3022-2023-453b-16a0-dbf697ee2c57",
+ "last_modified" : 1556584529537,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_FORMAT_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/TOP_SELLER.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/TOP_SELLER.json
new file mode 100644
index 0000000..c8bdc74
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "780d360b-bc9e-cffe-f536-3ac3cc7e2604",
+ "last_modified" : 1556584529540,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/TRANS_CNT.json
new file mode 100644
index 0000000..9e27167
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "053bc013-f728-1b09-326f-e258639cb752",
+ "last_modified" : 1556584529526,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/USER_COUNT_BITMAP.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/USER_COUNT_BITMAP.json
new file mode 100644
index 0000000..914d50f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_left_join_ready_2_segments/USER_COUNT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "93ea26ad-7751-08eb-c587-6a1443038eb4",
+ "last_modified" : 1556584529535,
+ "version" : "2.6.0.20500",
+ "name" : "USER_COUNT_BITMAP",
+ "cube_name" : "test_kylin_cube_without_slr_left_join_ready_2_segments",
+ "segments_name" : [ "19691231160000_20131112000000", "20131112000000_20131212000000" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/CAL_DT_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/CAL_DT_RAW.json
new file mode 100644
index 0000000..1e0c561
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "09fc721b-391b-45d7-2a76-1bd2cd8cf9e7",
+ "last_modified" : 1556584529575,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_MAX.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_MAX.json
new file mode 100644
index 0000000..55fbadb
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "ce7b3353-e8fb-4ba9-9d7c-d6462e171ef4",
+ "last_modified" : 1556584529560,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_MIN.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_MIN.json
new file mode 100644
index 0000000..648ff1e
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4dc3ed3c-f80c-91a5-5dc5-ab1ecd911d4a",
+ "last_modified" : 1556584529558,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_SUM.json
new file mode 100644
index 0000000..cef677a
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "6cc73d0e-c87f-17d8-b685-a5aa691db892",
+ "last_modified" : 1556584529554,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..9a6bb60
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "18b49642-aba2-2fc8-c0ba-71a79d385f4b",
+ "last_modified" : 1556584529566,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/LEAF_CATEG_ID_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/LEAF_CATEG_ID_RAW.json
new file mode 100644
index 0000000..ce9febf
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/LEAF_CATEG_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c5e9dd01-add7-4632-3870-c14ffdc7d0c2",
+ "last_modified" : 1556584529581,
+ "version" : "2.6.0.20500",
+ "name" : "LEAF_CATEG_ID_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/LSTG_FORMAT_NAME_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/LSTG_FORMAT_NAME_RAW.json
new file mode 100644
index 0000000..229e19d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/LSTG_FORMAT_NAME_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "9dc41f7e-338f-0329-df89-156c6b9f7b6e",
+ "last_modified" : 1556584529578,
+ "version" : "2.6.0.20500",
+ "name" : "LSTG_FORMAT_NAME_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/PRICE_RAW.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/PRICE_RAW.json
new file mode 100644
index 0000000..c1489ab
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "2f4a4b92-2d9a-2330-ea72-d960884a30ff",
+ "last_modified" : 1556584529584,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/SITE_EXTENDED_1.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/SITE_EXTENDED_1.json
new file mode 100644
index 0000000..f796f59
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/SITE_EXTENDED_1.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "bdd8d928-64fe-0e2c-7413-607e0550d292",
+ "last_modified" : 1556584529569,
+ "version" : "2.6.0.20500",
+ "name" : "SITE_EXTENDED_1",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/SITE_EXTENDED_2.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/SITE_EXTENDED_2.json
new file mode 100644
index 0000000..7429e00
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/SITE_EXTENDED_2.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "3aa75562-1b8d-0167-e4e5-0aea0dcdae9b",
+ "last_modified" : 1556584529572,
+ "version" : "2.6.0.20500",
+ "name" : "SITE_EXTENDED_2",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/TRANS_CNT.json b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/TRANS_CNT.json
new file mode 100644
index 0000000..88ba450
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_kylin_cube_without_slr_ready/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "532fb77f-237b-c42d-ca85-5e2061df6ccd",
+ "last_modified" : 1556584529563,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "test_kylin_cube_without_slr_ready",
+ "segments_name" : [ "67f668f6-dcff-4cb6-a89b-77f1119df8fa" ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/GMV_SUM.json
new file mode 100644
index 0000000..22296a5
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0ed4b930-f590-70c4-d91e-2f27b57da613",
+ "last_modified" : 1556584529589,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_streaming_join_table_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..e09e12f
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a6863648-042c-3ae9-5bef-df1738cabf32",
+ "last_modified" : 1556584529592,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_streaming_join_table_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/_COUNT_.json b/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/_COUNT_.json
new file mode 100644
index 0000000..f812058
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_join_table_cube/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "741e4def-7a49-9cd6-a796-4db1fa7bfd6f",
+ "last_modified" : 1556584529586,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "test_streaming_join_table_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_table_cube/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_streaming_table_cube/GMV_SUM.json
new file mode 100644
index 0000000..c0f8eb0
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_table_cube/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a5db8d10-607d-c7a0-0f74-e48764be24be",
+ "last_modified" : 1556584529598,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_streaming_table_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_table_cube/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_streaming_table_cube/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..722f15d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_table_cube/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a82f3ab7-3556-fce0-59c6-4e34b439551c",
+ "last_modified" : 1556584529601,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_streaming_table_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_table_cube/_COUNT_.json b/examples/test_case_data/localmeta/measure/test_streaming_table_cube/_COUNT_.json
new file mode 100644
index 0000000..6a19b12
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_table_cube/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "6553d4ad-b1f9-fb04-478d-dafdb3d25090",
+ "last_modified" : 1556584529595,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "test_streaming_table_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/GMV_PERCENTILE.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/GMV_PERCENTILE.json
new file mode 100644
index 0000000..400157c
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/GMV_PERCENTILE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "35256279-1a46-cfc7-2ab0-41b91c292214",
+ "last_modified" : 1556584529609,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_PERCENTILE",
+ "cube_name" : "test_streaming_v2_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/GMV_SUM.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/GMV_SUM.json
new file mode 100644
index 0000000..1b3bd70
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "c46277b8-7dc4-ae73-0b11-bba802a2c795",
+ "last_modified" : 1556584529607,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "test_streaming_v2_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/ITEM_COUNT_SUM.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..08e5eca
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "cb694b28-727d-f9a6-0b08-6ff0d33f9017",
+ "last_modified" : 1556584529612,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "test_streaming_v2_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/_COUNT_.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/_COUNT_.json
new file mode 100644
index 0000000..5d29edf
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_cube/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "2d01a19a-611b-1d0a-3f73-238f469d3cea",
+ "last_modified" : 1556584529604,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "test_streaming_v2_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/COUNTDISTINCT_LID.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/COUNTDISTINCT_LID.json
new file mode 100644
index 0000000..5a1329b
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/COUNTDISTINCT_LID.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "f7f7e92d-99e4-c41b-2a80-123b26b88a75",
+ "last_modified" : 1556584529632,
+ "version" : "2.6.0.20500",
+ "name" : "COUNTDISTINCT_LID",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/COUNTDISTINCT_UID.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/COUNTDISTINCT_UID.json
new file mode 100644
index 0000000..7690834
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/COUNTDISTINCT_UID.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "dbf5a094-9c14-394e-b844-9771a7c20751",
+ "last_modified" : 1556584529626,
+ "version" : "2.6.0.20500",
+ "name" : "COUNTDISTINCT_UID",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/MAX_EXPERIENCE.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/MAX_EXPERIENCE.json
new file mode 100644
index 0000000..89e5bbf
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/MAX_EXPERIENCE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "56812a73-a635-0304-d095-22826a9b8d96",
+ "last_modified" : 1556584529621,
+ "version" : "2.6.0.20500",
+ "name" : "MAX_EXPERIENCE",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/MIN_EXPERIENCE.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/MIN_EXPERIENCE.json
new file mode 100644
index 0000000..aa9741d
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/MIN_EXPERIENCE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7ea18289-1487-a49c-d548-b924607f484c",
+ "last_modified" : 1556584529623,
+ "version" : "2.6.0.20500",
+ "name" : "MIN_EXPERIENCE",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/PERCENTILE_REPUTATION.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/PERCENTILE_REPUTATION.json
new file mode 100644
index 0000000..c364a82
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/PERCENTILE_REPUTATION.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7156fe08-50ed-5e8d-3205-61fe9d6da509",
+ "last_modified" : 1556584529629,
+ "version" : "2.6.0.20500",
+ "name" : "PERCENTILE_REPUTATION",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/SUM_COINS.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/SUM_COINS.json
new file mode 100644
index 0000000..e6ede91
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/SUM_COINS.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "6d548cf2-dd34-2122-882d-a458aba0755b",
+ "last_modified" : 1556584529618,
+ "version" : "2.6.0.20500",
+ "name" : "SUM_COINS",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/_COUNT_.json b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/_COUNT_.json
new file mode 100644
index 0000000..ab3d274
--- /dev/null
+++ b/examples/test_case_data/localmeta/measure/test_streaming_v2_user_info_cube/_COUNT_.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "297a827e-aa66-288b-a12e-2c44ac56e42d",
+ "last_modified" : 1556584529615,
+ "version" : "2.6.0.20500",
+ "name" : "_COUNT_",
+ "cube_name" : "test_streaming_v2_user_info_cube",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/examples/test_case_data/measure/MAX_SELLER_ID.json b/examples/test_case_data/measure/MAX_SELLER_ID.json
new file mode 100644
index 0000000..bfad3fa
--- /dev/null
+++ b/examples/test_case_data/measure/MAX_SELLER_ID.json
@@ -0,0 +1,11 @@
+{
+ "name": "MAX_SELLER_ID",
+ "function": {
+ "expression": "MAX",
+ "parameter": {
+ "type": "column",
+ "value": "TEST_KYLIN_FACT.SELLER_ID"
+ },
+ "returntype": "decimal(19,4)"
+ }
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/BUYER_CONTACT.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/BUYER_CONTACT.json
new file mode 100644
index 0000000..2dea3e7
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/BUYER_CONTACT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "64629cc9-674d-f5ba-0598-0b07c6e5a49d",
+ "last_modified" : 1556980986018,
+ "version" : "2.6.0.20500",
+ "name" : "BUYER_CONTACT",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/CAL_DT_RAW.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/CAL_DT_RAW.json
new file mode 100644
index 0000000..d1efe45
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/CAL_DT_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "930aa6aa-9f30-1aaf-182a-814e853ca28e",
+ "last_modified" : 1556980986030,
+ "version" : "2.6.0.20500",
+ "name" : "CAL_DT_RAW",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/CORR_TRANS_ID_LSTG_SITE_ID.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/CORR_TRANS_ID_LSTG_SITE_ID.json
new file mode 100644
index 0000000..a1bb660
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/CORR_TRANS_ID_LSTG_SITE_ID.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "16cdccf4-0766-8f5b-4105-75b552e41a59",
+ "last_modified" : 1556980986036,
+ "version" : "2.6.0.20500",
+ "name" : "CORR_TRANS_ID_LSTG_SITE_ID",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_MAX.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_MAX.json
new file mode 100644
index 0000000..cc43703
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_MAX.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "a3139b9e-60c3-a9bc-7ff3-0a2d5c688091",
+ "last_modified" : 1556980985998,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MAX",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_MIN.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_MIN.json
new file mode 100644
index 0000000..60be7b1
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_MIN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "87478106-6125-9eb0-3333-14728c4f8384",
+ "last_modified" : 1556980985995,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_MIN",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_SUM.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_SUM.json
new file mode 100644
index 0000000..397f756
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GMV_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "ebc22078-1966-272f-0893-c48f4ef71b2e",
+ "last_modified" : 1556980985991,
+ "version" : "2.6.0.20500",
+ "name" : "GMV_SUM",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GVM_PERCENTILE.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GVM_PERCENTILE.json
new file mode 100644
index 0000000..63178aa
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/GVM_PERCENTILE.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "58b5b26f-03fe-305b-8cd7-e2ccf4245b44",
+ "last_modified" : 1556980986033,
+ "version" : "2.6.0.20500",
+ "name" : "GVM_PERCENTILE",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/ITEM_COUNT_SUM.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/ITEM_COUNT_SUM.json
new file mode 100644
index 0000000..1c8cf35
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/ITEM_COUNT_SUM.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "37b51e30-fc7d-f843-06ac-35bc259e145a",
+ "last_modified" : 1556980985988,
+ "version" : "2.6.0.20500",
+ "name" : "ITEM_COUNT_SUM",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/PRICE_RAW.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/PRICE_RAW.json
new file mode 100644
index 0000000..6d9aeaa
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/PRICE_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "4c9fc911-ecb1-2603-95d3-023f68d47b93",
+ "last_modified" : 1556980986027,
+ "version" : "2.6.0.20500",
+ "name" : "PRICE_RAW",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_CONTACT.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_CONTACT.json
new file mode 100644
index 0000000..5fb92eb
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_CONTACT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "66ca4075-c335-4293-60d4-ef475c7a3015",
+ "last_modified" : 1556980986021,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_CONTACT",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_FORMAT_HLL.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_FORMAT_HLL.json
new file mode 100644
index 0000000..8b66719
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_FORMAT_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "d785181a-8d7e-d613-89b9-a59046932919",
+ "last_modified" : 1556980986004,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_FORMAT_HLL",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_HLL.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_HLL.json
new file mode 100644
index 0000000..eef1a98
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/SELLER_HLL.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "0fee3058-d48c-c955-6a1d-27cce3ddad07",
+ "last_modified" : 1556980986001,
+ "version" : "2.6.0.20500",
+ "name" : "SELLER_HLL",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TEST_COUNT_DISTINCT_BITMAP.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TEST_COUNT_DISTINCT_BITMAP.json
new file mode 100644
index 0000000..34c1c4b
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TEST_COUNT_DISTINCT_BITMAP.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "8347f264-ba0b-e646-bb87-2a52c1aa2078",
+ "last_modified" : 1556980986012,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_COUNT_DISTINCT_BITMAP",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TEST_EXTENDED_COLUMN.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TEST_EXTENDED_COLUMN.json
new file mode 100644
index 0000000..c401ff9
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TEST_EXTENDED_COLUMN.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "41d1d993-1663-0c39-3d04-41a89420dc29",
+ "last_modified" : 1556980986015,
+ "version" : "2.6.0.20500",
+ "name" : "TEST_EXTENDED_COLUMN",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TOP_SELLER.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TOP_SELLER.json
new file mode 100644
index 0000000..37aa43f
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TOP_SELLER.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "98a70b36-561b-7519-c527-6e314832cd49",
+ "last_modified" : 1556980986008,
+ "version" : "2.6.0.20500",
+ "name" : "TOP_SELLER",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TRANS_CNT.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TRANS_CNT.json
new file mode 100644
index 0000000..8c7319d
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TRANS_CNT.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "7bc0aa31-466a-5bdb-5ecb-9c668fe3df2f",
+ "last_modified" : 1556980985985,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_CNT",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file
diff --git a/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TRANS_ID_RAW.json b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TRANS_ID_RAW.json
new file mode 100644
index 0000000..9e80d63
--- /dev/null
+++ b/source-jdbc/src/test/resources/ut_meta/jdbc_source/measure/ut_jdbc_shard/TRANS_ID_RAW.json
@@ -0,0 +1,9 @@
+{
+ "uuid" : "e5f7d731-5860-7a3c-1356-b4d256fc7eb8",
+ "last_modified" : 1556980986024,
+ "version" : "2.6.0.20500",
+ "name" : "TRANS_ID_RAW",
+ "cube_name" : "ut_jdbc_shard",
+ "segments_name" : [ ],
+ "online" : true
+}
\ No newline at end of file