KYLIN-2575 Experimental feature: Computed Column
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/9a812d5f Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/9a812d5f Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/9a812d5f Branch: refs/heads/KYLIN-2624 Commit: 9a812d5fc917ddcdb736cd1c91fdfe9c933e603a Parents: d6fdda2 Author: Hongbin Ma <mahong...@apache.org> Authored: Mon May 8 15:49:57 2017 +0800 Committer: liyang-gmt8 <liy...@apache.org> Committed: Mon May 8 16:01:48 2017 +0800 ---------------------------------------------------------------------- .../kylin/cube/CubeCapabilityChecker.java | 11 +- .../java/org/apache/kylin/cube/JoinChecker.java | 60 - .../org/apache/kylin/cube/cuboid/CuboidCLI.java | 7 + .../org/apache/kylin/cube/model/CubeDesc.java | 12 +- .../kylin/cube/cuboid/CuboidSchedulerTest.java | 23 + .../model/validation/rule/FunctionRuleTest.java | 11 +- .../org/apache/kylin/job/JoinedFlatTable.java | 4 +- .../apache/kylin/metadata/MetadataManager.java | 31 +- .../apache/kylin/metadata/model/ColumnDesc.java | 41 +- .../metadata/model/ComputedColumnDesc.java | 95 ++ .../kylin/metadata/model/DataModelDesc.java | 81 +- .../apache/kylin/metadata/model/JoinsTree.java | 2 +- .../kylin/metadata/model/PartitionDesc.java | 10 +- .../apache/kylin/metadata/model/TableDesc.java | 35 +- .../apache/kylin/metadata/model/TableRef.java | 14 +- .../apache/kylin/metadata/model/TblColRef.java | 36 +- .../kylin/metadata/project/ProjectL2Cache.java | 13 +- .../kylin/metadata/model/DataModelDescTest.java | 15 +- .../localmeta/cube_desc/ci_inner_join_cube.json | 1016 ++++++++++------- .../localmeta/cube_desc/ci_left_join_cube.json | 1036 ++++++++++-------- .../model_desc/ci_inner_join_model.json | 37 +- .../model_desc/ci_left_join_model.json | 37 +- .../test_case_data/sandbox/kylin.properties | 2 +- .../kylin/query/CompareQueryBySuffix.java | 37 + .../kylin/query/ICompareQueryTranslator.java | 29 + .../apache/kylin/query/ITKylinQueryTest.java | 5 + .../org/apache/kylin/query/KylinTestBase.java | 25 +- .../query/sql_computedcolumn/query01.sql | 14 + .../sql_computedcolumn/query01.sql.compare | 14 + .../query/sql_computedcolumn/query02.sql | 21 + .../sql_computedcolumn/query02.sql.compare | 21 + .../query/sql_verifyCount/query01.sql.expected | 2 +- .../query/sql_verifyCount/query03.sql.expected | 2 +- .../query/sql_verifyCount/query04.sql.expected | 2 +- .../apache/kylin/query/schema/OLAPSchema.java | 2 +- .../kylin/rest/controller/ModelController.java | 2 +- .../kylin/rest/service/CacheServiceTest.java | 1 - .../kylin/rest/service/ModelServiceTest.java | 97 ++ .../apache/kylin/source/hive/SchemaChecker.java | 2 +- 39 files changed, 1894 insertions(+), 1011 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java ---------------------------------------------------------------------- diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java index c45144b..20cb0a9 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java @@ -52,12 +52,7 @@ public class CubeCapabilityChecker { CapabilityResult result = new CapabilityResult(); result.capable = false; - // match joins - boolean isJoinMatch = JoinChecker.isJoinMatch(digest.joinDescs, cube); - if (!isJoinMatch) { - logger.info("Exclude cube " + cube.getName() + " because unmatched joins"); - return result; - } + // match joins is ensured at model select // dimensions & measures Collection<TblColRef> dimensionColumns = getDimensionColumns(digest); @@ -106,12 +101,12 @@ public class CubeCapabilityChecker { } if (!unmatchedDimensions.isEmpty()) { - logger.info("Exclude cube " + cube.getName() + " because unmatched dimensions"); + logger.info("Exclude cube " + cube.getName() + " because unmatched dimensions: " + unmatchedDimensions); return result; } if (!unmatchedAggregations.isEmpty()) { - logger.info("Exclude cube " + cube.getName() + " because unmatched aggregations"); + logger.info("Exclude cube " + cube.getName() + " because unmatched aggregations: " + unmatchedAggregations); return result; } http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-cube/src/main/java/org/apache/kylin/cube/JoinChecker.java ---------------------------------------------------------------------- diff --git a/core-cube/src/main/java/org/apache/kylin/cube/JoinChecker.java b/core-cube/src/main/java/org/apache/kylin/cube/JoinChecker.java deleted file mode 100644 index 9068449..0000000 --- a/core-cube/src/main/java/org/apache/kylin/cube/JoinChecker.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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; - -import java.util.Collection; - -import org.apache.kylin.metadata.model.JoinDesc; -import org.apache.kylin.metadata.realization.IRealization; - -public class JoinChecker { - - // given ModelChooser has done the model join matching already, this method seems useless - public static boolean isJoinMatch(Collection<JoinDesc> joins, IRealization realization) { -// List<JoinDesc> realizationsJoins = Lists.newArrayList(); -// for (JoinTableDesc joinTable : realization.getModel().getJoinTables()) { -// realizationsJoins.add(joinTable.getJoin()); -// } -// -// for (JoinDesc j : joins) { -// // optiq engine can't decide which one is fk or pk -// String pTable = j.getPrimaryKeyColumns()[0].getTable(); -// String factTable = realization.getModel().getRootFactTable().getTableIdentity(); -// if (factTable.equals(pTable)) { -// j.swapPKFK(); -// } -// -// // check primary key, all PK column should refer to same tale, the Fact Table of cube. -// // Using first column's table name to check. -// String fTable = j.getForeignKeyColumns()[0].getTable(); -// if (!factTable.equals(fTable)) { -// logger.info("Fact Table" + factTable + " not matched in join: " + j + " on cube " + realization.getName()); -// return false; -// } -// -// // The hashcode() function of JoinDesc has been overwritten, -// // which takes into consideration: pk,fk,jointype -// if (!realizationsJoins.contains(j)) { -// logger.info("Query joins don't macth on cube " + realization.getName()); -// return false; -// } -// } - return true; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-cube/src/main/java/org/apache/kylin/cube/cuboid/CuboidCLI.java ---------------------------------------------------------------------- diff --git a/core-cube/src/main/java/org/apache/kylin/cube/cuboid/CuboidCLI.java b/core-cube/src/main/java/org/apache/kylin/cube/cuboid/CuboidCLI.java index 05efb5e..535f77a 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/cuboid/CuboidCLI.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/cuboid/CuboidCLI.java @@ -132,10 +132,17 @@ public class CuboidCLI { while (!currentQueue.isEmpty()) { long cuboid = currentQueue.pop(); Collection<Long> spnanningCuboids = scheduler.getSpanningCuboid(cuboid); + nextQueue.addAll(spnanningCuboids); } currentQueue = nextQueue; nextQueue = new LinkedList<Long>(); + + if (i == levels) { + if (!currentQueue.isEmpty()) { + throw new IllegalStateException(); + } + } } return allLevelCounts; http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java ---------------------------------------------------------------------- diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java b/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java index 53c11a3..dfbe6e7 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java @@ -26,6 +26,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -887,7 +888,7 @@ public class CubeDesc extends RootPersistentEntity implements IEngineAware { } } } - + return initDimensionColRef(col); } @@ -939,6 +940,7 @@ public class CubeDesc extends RootPersistentEntity implements IEngineAware { for (int i = 0; i < measures.size(); i++) measureIndexLookup.put(measures.get(i).getName(), i); + BitSet checkEachMeasureExist = new BitSet(); for (HBaseColumnFamilyDesc cf : getHbaseMapping().getColumnFamily()) { for (HBaseColumnDesc c : cf.getColumns()) { String[] colMeasureRefs = c.getMeasureRefs(); @@ -946,13 +948,21 @@ public class CubeDesc extends RootPersistentEntity implements IEngineAware { int[] measureIndex = new int[colMeasureRefs.length]; for (int i = 0; i < colMeasureRefs.length; i++) { measureDescs[i] = measureLookup.get(colMeasureRefs[i]); + checkState(measureDescs[i] != null, "measure desc at (%s) is null", i); measureIndex[i] = measureIndexLookup.get(colMeasureRefs[i]); + checkState(measureIndex[i] >= 0, "measure index at (%s) not positive", i); + + checkEachMeasureExist.set(measureIndex[i]); } c.setMeasures(measureDescs); c.setMeasureIndex(measureIndex); c.setColumnFamilyName(cf.getName()); } } + + for (int i = 0; i < measures.size(); i++) { + checkState(checkEachMeasureExist.get(i), "measure (%s) does not exist in column familyï¼or measure duplicates", measures.get(i)); + } } private void initDictionaryDesc() { http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-cube/src/test/java/org/apache/kylin/cube/cuboid/CuboidSchedulerTest.java ---------------------------------------------------------------------- diff --git a/core-cube/src/test/java/org/apache/kylin/cube/cuboid/CuboidSchedulerTest.java b/core-cube/src/test/java/org/apache/kylin/cube/cuboid/CuboidSchedulerTest.java index 7db616e..6457770 100644 --- a/core-cube/src/test/java/org/apache/kylin/cube/cuboid/CuboidSchedulerTest.java +++ b/core-cube/src/test/java/org/apache/kylin/cube/cuboid/CuboidSchedulerTest.java @@ -94,6 +94,10 @@ public class CuboidSchedulerTest extends LocalFileMetadataTestCase { private CubeDesc getSSBCubeDesc() { return getCubeDescManager().getCubeDesc("ssb"); } + + private CubeDesc getCIInnerJoinCube() { + return getCubeDescManager().getCubeDesc("ci_inner_join_cube"); + } private void testSpanningAndGetParent(CuboidScheduler scheduler, CubeDesc cube, long[] cuboidIds) { for (long cuboidId : cuboidIds) { @@ -219,6 +223,12 @@ public class CuboidSchedulerTest extends LocalFileMetadataTestCase { CubeDesc cube = getSSBCubeDesc(); CuboidCLI.simulateCuboidGeneration(cube, true); } + + @Test + public void testCuboidGeneration7() { + CubeDesc cube = getCIInnerJoinCube(); + CuboidCLI.simulateCuboidGeneration(cube, true); + } @Test public void testCuboidCounts1() { @@ -286,6 +296,19 @@ public class CuboidSchedulerTest extends LocalFileMetadataTestCase { } @Test + public void testCuboidCounts6() { + CubeDesc cube = getCIInnerJoinCube(); + CuboidScheduler cuboidScheduler = new CuboidScheduler(cube); + int[] counts = CuboidCLI.calculateAllLevelCount(cube); + printCount(counts); + int sum = 0; + for (Integer x : counts) { + sum += x; + } + assertEquals(cuboidScheduler.getCuboidCount(), sum); + } + + @Test public void testCuboid_onlyBaseCuboid() { for (File f : new File(LocalFileMetadataTestCase.LOCALMETA_TEMP_DATA, "cube_desc").listFiles()) { if (f.getName().endsWith(".bad")) { http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java ---------------------------------------------------------------------- diff --git a/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java b/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java index a3456c4..18d84c3 100644 --- a/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java +++ b/core-cube/src/test/java/org/apache/kylin/cube/model/validation/rule/FunctionRuleTest.java @@ -18,7 +18,6 @@ package org.apache.kylin.cube.model.validation.rule; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; @@ -62,10 +61,8 @@ public class FunctionRuleTest extends LocalFileMetadataTestCase { assertTrue(vContext.getResults().length == 0); } - @Test + @Test(expected = IllegalStateException.class) public void testValidateMeasureNamesDuplicated() throws IOException { - FunctionRule rule = new FunctionRule(); - File f = new File(LocalFileMetadataTestCase.LOCALMETA_TEST_DATA + "/cube_desc/ssb.json"); CubeDesc desc = JsonUtil.readValue(new FileInputStream(f), CubeDesc.class); @@ -73,11 +70,5 @@ public class FunctionRuleTest extends LocalFileMetadataTestCase { desc.getMeasures().add(measureDescDuplicated); desc.init(config); - ValidateContext vContext = new ValidateContext(); - rule.validate(desc, vContext); - - vContext.print(System.out); - assertTrue(vContext.getResults().length >= 1); - assertEquals("There is duplicated measure's name: " + measureDescDuplicated.getName(), vContext.getResults()[0].getMessage()); } } http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-job/src/main/java/org/apache/kylin/job/JoinedFlatTable.java ---------------------------------------------------------------------- diff --git a/core-job/src/main/java/org/apache/kylin/job/JoinedFlatTable.java b/core-job/src/main/java/org/apache/kylin/job/JoinedFlatTable.java index 16086e3..4665465 100644 --- a/core-job/src/main/java/org/apache/kylin/job/JoinedFlatTable.java +++ b/core-job/src/main/java/org/apache/kylin/job/JoinedFlatTable.java @@ -109,7 +109,7 @@ public class JoinedFlatTable { if (i > 0) { sql.append(","); } - sql.append(col.getTableAlias() + "." + col.getName() + "\n"); + sql.append(col.getExpressionInSourceDB() + "\n"); } appendJoinStatement(flatDesc, sql); appendWhereStatement(flatDesc, sql); @@ -149,7 +149,7 @@ public class JoinedFlatTable { if (i > 0) { sql.append(" AND "); } - sql.append(fk[i].getTableAlias() + "." + fk[i].getName() + " = " + pk[i].getTableAlias() + "." + pk[i].getName()); + sql.append(fk[i].getIdentity() + " = " + pk[i].getIdentity()); } sql.append("\n"); http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/core-metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java index f17983f..b3ca14a 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -40,6 +41,7 @@ import org.apache.kylin.metadata.cachesync.Broadcaster; import org.apache.kylin.metadata.cachesync.Broadcaster.Event; import org.apache.kylin.metadata.cachesync.CaseInsensitiveStringCache; import org.apache.kylin.metadata.model.ColumnDesc; +import org.apache.kylin.metadata.model.ComputedColumnDesc; import org.apache.kylin.metadata.model.DataModelDesc; import org.apache.kylin.metadata.model.ExternalFilterDesc; import org.apache.kylin.metadata.model.TableDesc; @@ -114,6 +116,18 @@ public class MetadataManager { // name => External Filter Desc private CaseInsensitiveStringCache<ExternalFilterDesc> extFilterMap; + public static class CCInfo { + public ComputedColumnDesc computedColumnDesc; + public Set<DataModelDesc> dataModelDescs; + + public CCInfo(ComputedColumnDesc computedColumnDesc, Set<DataModelDesc> dataModelDescs) { + this.computedColumnDesc = computedColumnDesc; + this.dataModelDescs = dataModelDescs; + } + } + + private Map<String, CCInfo> ccInfoMap = Maps.newHashMap();// this is to check any two models won't conflict computed columns + private MetadataManager(KylinConfig config) throws IOException { init(config); } @@ -343,8 +357,9 @@ public class MetadataManager { @Override public void onProjectSchemaChange(Broadcaster broadcaster, String project) throws IOException { + ccInfoMap.clear(); for (String model : ProjectManager.getInstance(config).getProject(project).getModels()) { - reloadDataModelDesc(model); + reloadDataModelDescAt(DataModelDesc.concatResourcePath(model)); } } @@ -353,7 +368,7 @@ public class MetadataManager { if (event == Event.DROP) dataModelDescMap.removeLocal(cacheKey); else - reloadDataModelDesc(cacheKey); + reloadDataModelDescAt(DataModelDesc.concatResourcePath(cacheKey)); for (ProjectInstance prj : ProjectManager.getInstance(config).findProjectsByModel(cacheKey)) { broadcaster.notifyProjectSchemaUpdate(prj.getName()); @@ -568,7 +583,9 @@ public class MetadataManager { List<String> paths = store.collectResourceRecursively(ResourceStore.DATA_MODEL_DESC_RESOURCE_ROOT, MetadataConstants.FILE_SURFIX); for (String path : paths) { + try { + logger.info("Reloading data model at " + path); reloadDataModelDescAt(path); } catch (IllegalStateException e) { logger.error("Error to load DataModel at " + path, e); @@ -579,15 +596,11 @@ public class MetadataManager { logger.debug("Loaded " + dataModelDescMap.size() + " DataModel(s)"); } - public DataModelDesc reloadDataModelDesc(String name) { - return reloadDataModelDescAt(DataModelDesc.concatResourcePath(name)); - } - - private DataModelDesc reloadDataModelDescAt(String path) { + public DataModelDesc reloadDataModelDescAt(String path) { ResourceStore store = getStore(); try { DataModelDesc dataModelDesc = store.getResource(path, DataModelDesc.class, MODELDESC_SERIALIZER); - dataModelDesc.init(config, this.getAllTablesMap()); + dataModelDesc.init(config, this.getAllTablesMap(), this.ccInfoMap); dataModelDescMap.putLocal(dataModelDesc.getName(), dataModelDesc); return dataModelDesc; } catch (Exception e) { @@ -635,7 +648,7 @@ public class MetadataManager { } private DataModelDesc saveDataModelDesc(DataModelDesc dataModelDesc) throws IOException { - dataModelDesc.init(config, this.getAllTablesMap()); + dataModelDesc.init(config, this.getAllTablesMap(), this.ccInfoMap); String path = dataModelDesc.getResourcePath(); getStore().putResource(path, dataModelDesc, MODELDESC_SERIALIZER); http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java index e5b51e4..2cd4964 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java @@ -19,6 +19,7 @@ package org.apache.kylin.metadata.model; import java.io.Serializable; +import java.util.regex.Pattern; import org.apache.kylin.metadata.datatype.DataType; @@ -26,6 +27,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; /** * Column Metadata from Source. All name should be uppercase. @@ -37,10 +39,13 @@ public class ColumnDesc implements Serializable { @JsonProperty("id") private String id; + @JsonProperty("name") private String name; + @JsonProperty("datatype") private String datatype; + @JsonProperty("comment") @JsonInclude(JsonInclude.Include.NON_NULL) private String comment; @@ -62,10 +67,31 @@ public class ColumnDesc implements Serializable { private boolean isNullable = true; private TblColRef ref; + private String computedColumnExpr = null;//if null, it's not a computed column public ColumnDesc() { // default constructor for Jackson } + public ColumnDesc(ColumnDesc other) { + this.id = other.id; + this.name = other.name; + this.datatype = other.datatype; + this.dataGen = other.datatype; + this.comment = other.comment; + this.dataGen = other.dataGen; + this.index = other.index; + } + + public ColumnDesc(String id, String name, String datatype, String comment, String dataGen, String index, String computedColumnExpr) { + this.id = id; + this.name = name; + this.datatype = datatype; + this.comment = comment; + this.dataGen = dataGen; + this.index = index; + this.computedColumnExpr = computedColumnExpr; + } + /** Use TableRef.getColumn() instead */ @Deprecated public TblColRef getRef() { @@ -156,7 +182,7 @@ public class ColumnDesc implements Serializable { public void setNullable(boolean nullable) { this.isNullable = nullable; } - + public String getDataGen() { return dataGen; } @@ -165,6 +191,17 @@ public class ColumnDesc implements Serializable { return index; } + public String getComputedColumnExpr(String tableAlias, String tableIdentity) { + Preconditions.checkState(computedColumnExpr != null); + + //http://stackoverflow.com/questions/5054995/how-to-replace-case-insensitive-literal-substrings-in-java + return computedColumnExpr.replaceAll("(?i)" + Pattern.quote(tableIdentity), tableAlias); + } + + public boolean isComputedColumnn() { + return computedColumnExpr != null; + } + public void init(TableDesc table) { this.table = table; @@ -212,7 +249,7 @@ public class ColumnDesc implements Serializable { return false; } else if (!table.getIdentity().equals(other.table.getIdentity())) return false; - + return true; } http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/ComputedColumnDesc.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ComputedColumnDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ComputedColumnDesc.java new file mode 100644 index 0000000..ac5830f --- /dev/null +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ComputedColumnDesc.java @@ -0,0 +1,95 @@ +/* + * 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 com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; + +public class ComputedColumnDesc { + @JsonProperty + private String tableIdentity; + @JsonProperty + private String columnName; + @JsonProperty + private String expression; + @JsonProperty + private String datatype; + @JsonProperty + private String comment; + + public void init() { + Preconditions.checkNotNull(tableIdentity, "tableIdentity is null"); + Preconditions.checkNotNull(columnName, "columnName is null"); + Preconditions.checkNotNull(expression, "expression is null"); + Preconditions.checkNotNull(datatype, "datatype is null"); + + tableIdentity = tableIdentity.toUpperCase(); + columnName = columnName.toUpperCase(); + } + + public String getFullName() { + return tableIdentity + "." + columnName; + } + + public String getTableIdentity() { + return tableIdentity; + } + + public String getColumnName() { + return columnName; + } + + public String getExpression() { + return expression; + } + + public String getDatatype() { + return datatype; + } + + public String getComment() { + return comment; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ComputedColumnDesc that = (ComputedColumnDesc) o; + + if (!tableIdentity.equals(that.tableIdentity)) + return false; + if (!columnName.equals(that.columnName)) + return false; + if (!expression.equals(that.expression)) + return false; + return datatype.equals(that.datatype); + } + + @Override + public int hashCode() { + int result = tableIdentity.hashCode(); + result = 31 * result + columnName.hashCode(); + result = 31 * result + expression.hashCode(); + result = 31 * result + datatype.hashCode(); + return result; + } +} http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java index 3669109..2174b7a 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java @@ -18,6 +18,8 @@ package org.apache.kylin.metadata.model; +import static org.apache.kylin.metadata.MetadataManager.CCInfo; + import java.io.Serializable; import java.util.ArrayDeque; import java.util.ArrayList; @@ -28,6 +30,9 @@ import java.util.Map; import java.util.Queue; import java.util.Set; +import javax.annotation.Nullable; + +import org.apache.commons.lang.mutable.MutableInt; import org.apache.commons.lang3.ArrayUtils; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.persistence.ResourceStore; @@ -42,6 +47,9 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -96,6 +104,10 @@ public class DataModelDesc extends RootPersistentEntity { @JsonProperty("capacity") private RealizationCapacity capacity = RealizationCapacity.MEDIUM; + @JsonProperty("computed_columns") + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + private List<ComputedColumnDesc> computedColumnDescs = Lists.newArrayList(); + // computed attributes private TableRef rootFactTableRef; private Set<TableRef> factTableRefs = Sets.newLinkedHashSet(); @@ -291,7 +303,16 @@ public class DataModelDesc extends RootPersistentEntity { throw new IllegalArgumentException("Table not found by " + tableIdentity + " in model " + name); } - public void init(KylinConfig config, Map<String, TableDesc> tables) { + public void init(KylinConfig config, Map<String, TableDesc> originalTables, Map<String, CCInfo> ccInfoMap) { + //tweak the tables according to Computed Columns defined in model + Map<String, TableDesc> tables = Maps.newHashMap(); + for (Map.Entry<String, TableDesc> entry : originalTables.entrySet()) { + String s = entry.getKey(); + TableDesc tableDesc = entry.getValue(); + TableDesc extendedTableDesc = tableDesc.appendColumns(createComputedColumns(tableDesc)); + tables.put(s, extendedTableDesc); + } + this.config = config; initJoinTablesForUpgrade(); @@ -301,13 +322,32 @@ public class DataModelDesc extends RootPersistentEntity { initJoinsTree(); initDimensionsAndMetrics(); initPartitionDesc(); + initComputedColumns(ccInfoMap); boolean reinit = validate(); if (reinit) { // model slightly changed by validate() and must init() again - init(config, tables); + init(config, tables, ccInfoMap); } } + private ColumnDesc[] createComputedColumns(final TableDesc tableDesc) { + final MutableInt id = new MutableInt(tableDesc.getColumnCount()); + return FluentIterable.from(this.computedColumnDescs).filter(new Predicate<ComputedColumnDesc>() { + @Override + public boolean apply(@Nullable ComputedColumnDesc input) { + return tableDesc.getIdentity().equalsIgnoreCase(input.getTableIdentity()); + } + }).transform(new Function<ComputedColumnDesc, ColumnDesc>() { + @Nullable + @Override + public ColumnDesc apply(@Nullable ComputedColumnDesc input) { + id.increment(); + ColumnDesc columnDesc = new ColumnDesc(id.toString(), input.getColumnName(), input.getDatatype(), input.getComment(), null, null, input.getExpression()); + return columnDesc; + } + }).toArray(ColumnDesc.class); + } + private void initJoinTablesForUpgrade() { if (joinTables == null) { joinTables = new JoinTableDesc[0]; @@ -333,6 +373,7 @@ public class DataModelDesc extends RootPersistentEntity { TableDesc rootDesc = tables.get(rootFactTable); rootFactTableRef = new TableRef(this, rootDesc.getName(), rootDesc); + addAlias(rootFactTableRef); factTableRefs.add(rootFactTableRef); @@ -346,7 +387,9 @@ public class DataModelDesc extends RootPersistentEntity { String alias = join.getAlias(); if (alias == null) alias = tableDesc.getName(); + TableRef ref = new TableRef(this, alias, tableDesc); + join.setTableRef(ref); addAlias(ref); (join.getKind() == TableKind.LOOKUP ? lookupTableRefs : factTableRefs).add(ref); @@ -390,6 +433,30 @@ public class DataModelDesc extends RootPersistentEntity { this.partitionDesc.init(this); } + private void initComputedColumns(Map<String, CCInfo> ccInfoMap) { + Set<String> ccSet = Sets.newHashSet();//make sure cc name does not duplicate within this model + + for (ComputedColumnDesc computedColumnDesc : this.computedColumnDescs) { + computedColumnDesc.init(); + + if (ccSet.contains(computedColumnDesc.getFullName())) { + throw new IllegalArgumentException(String.format("More than one computed column named %s exist in model %s", computedColumnDesc.getFullName(), this.getName())); + } else { + ccSet.add(computedColumnDesc.getFullName()); + } + + CCInfo other = ccInfoMap.get(computedColumnDesc.getFullName()); + if (other == null || (other.dataModelDescs.size() == 1 && other.dataModelDescs.contains(this))) { + ccInfoMap.put(computedColumnDesc.getFullName(), new CCInfo(computedColumnDesc, Sets.<DataModelDesc> newHashSet(this))); + } else if (other.computedColumnDesc.equals(computedColumnDesc)) { + other.dataModelDescs.add(this); + } else { + throw new IllegalStateException(String.format("Computed column named %s is already defined in other models: %s. Please change another name, or try to keep consistent definition", // + computedColumnDesc.getFullName(), other.dataModelDescs)); + } + } + } + private void initJoinColumns() { for (JoinTableDesc joinTable : joinTables) { @@ -568,10 +635,8 @@ public class DataModelDesc extends RootPersistentEntity { } /** - * @param message - * error message - * @param silent - * if throw exception + * @param message error message + * @param silent if throw exception */ public void addError(String message, boolean silent) { if (!silent) { @@ -627,6 +692,10 @@ public class DataModelDesc extends RootPersistentEntity { return dimensions; } + public List<ComputedColumnDesc> getComputedColumnDescs() { + return computedColumnDescs; + } + public String[] getMetrics() { return metrics; } http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsTree.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsTree.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsTree.java index 8e2192f..7db730e 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsTree.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsTree.java @@ -93,7 +93,7 @@ public class JoinsTree implements Serializable { boolean matches = false; if (chain.join == null) { - matches = anotherChain.join == null && chain.table.getTableDesc().equals(anotherChain.table.getTableDesc()); + matches = anotherChain.join == null && chain.table.getTableDesc().getIdentity().equals(anotherChain.table.getTableDesc().getIdentity()); } else { matches = chain.join.matches(anotherChain.join) && matchChain(chain.fkSide, anotherChain.fkSide, matchUp); } http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java index 38c2de5..3c00149 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java @@ -201,7 +201,7 @@ public class PartitionDesc implements Serializable { } private static void buildSingleColumnRangeCondAsTimeMillis(StringBuilder builder, TblColRef partitionColumn, long startInclusive, long endExclusive) { - String partitionColumnName = partitionColumn.getTableAlias() + "." + partitionColumn.getName(); + String partitionColumnName = partitionColumn.getIdentity(); if (startInclusive > 0) { builder.append(partitionColumnName + " >= " + startInclusive); builder.append(" AND "); @@ -210,7 +210,7 @@ public class PartitionDesc implements Serializable { } private static void buildSingleColumnRangeCondAsYmdInt(StringBuilder builder, TblColRef partitionColumn, long startInclusive, long endExclusive) { - String partitionColumnName = partitionColumn.getTableAlias() + "." + partitionColumn.getName(); + String partitionColumnName = partitionColumn.getIdentity(); if (startInclusive > 0) { builder.append(partitionColumnName + " >= " + DateFormat.formatToDateStr(startInclusive, DateFormat.COMPACT_DATE_PATTERN)); builder.append(" AND "); @@ -219,7 +219,7 @@ public class PartitionDesc implements Serializable { } private static void buildSingleColumnRangeCondition(StringBuilder builder, TblColRef partitionColumn, long startInclusive, long endExclusive, String partitionColumnDateFormat) { - String partitionColumnName = partitionColumn.getTableAlias() + "." + partitionColumn.getName(); + String partitionColumnName = partitionColumn.getIdentity(); if (startInclusive > 0) { builder.append(partitionColumnName + " >= '" + DateFormat.formatToDateStr(startInclusive, partitionColumnDateFormat) + "'"); builder.append(" AND "); @@ -228,8 +228,8 @@ public class PartitionDesc implements Serializable { } private static void buildMultipleColumnRangeCondition(StringBuilder builder, TblColRef partitionDateColumn, TblColRef partitionTimeColumn, long startInclusive, long endExclusive, String partitionColumnDateFormat, String partitionColumnTimeFormat) { - String partitionDateColumnName = partitionDateColumn.getTableAlias() + "." + partitionDateColumn.getName(); - String partitionTimeColumnName = partitionTimeColumn.getTableAlias() + "." + partitionTimeColumn.getName(); + String partitionDateColumnName = partitionDateColumn.getIdentity(); + String partitionTimeColumnName = partitionTimeColumn.getIdentity(); if (startInclusive > 0) { builder.append("("); builder.append("("); http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java index b4d49fb..b388f11 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java @@ -61,10 +61,34 @@ public class TableDesc extends RootPersistentEntity implements ISourceAware { } public TableDesc(TableDesc other) { - this.name = other.getName(); - this.columns = other.getColumns(); + this.name = other.name; + this.sourceType = other.sourceType; this.database.setName(other.getDatabase()); - this.tableType = other.getTableType(); + this.tableType = other.tableType; + this.dataGen = other.dataGen; + this.columns = new ColumnDesc[other.columns.length]; + for (int i = 0; i < other.columns.length; i++) { + this.columns[i] = new ColumnDesc(other.columns[i]); + this.columns[i].init(this); + } + } + + public TableDesc appendColumns(ColumnDesc[] computedColumns) { + if (computedColumns == null || computedColumns.length == 0) { + return this; + } + + TableDesc ret = new TableDesc(this);//deep copy of the table desc + ColumnDesc[] origin = ret.columns; + ret.columns = new ColumnDesc[computedColumns.length + origin.length]; + for (int i = 0; i < origin.length; i++) { + ret.columns[i] = origin[i]; + } + for (int i = 0; i < computedColumns.length; i++) { + computedColumns[i].init(ret); + ret.columns[i + this.columns.length] = computedColumns[i]; + } + return ret; } public ColumnDesc findColumnByName(String name) { @@ -153,7 +177,12 @@ public class TableDesc extends RootPersistentEntity implements ISourceAware { } public int getMaxColumnIndex() { + if (columns == null) { + return -1; + } + int max = -1; + for (ColumnDesc col : columns) { int idx = col.getZeroBasedIndex(); max = Math.max(max, idx); http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableRef.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableRef.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableRef.java index 6f15f3c..f4aec12 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableRef.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableRef.java @@ -18,14 +18,14 @@ package org.apache.kylin.metadata.model; -import com.google.common.collect.Maps; - import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.Map; -public class TableRef implements Serializable{ +import com.google.common.collect.Maps; + +public class TableRef implements Serializable { final transient private DataModelDesc model; final private String alias; @@ -68,11 +68,11 @@ public class TableRef implements Serializable{ public TblColRef getColumn(String name) { return columns.get(name); } - + public Collection<TblColRef> getColumns() { return Collections.unmodifiableCollection(columns.values()); } - + // for test only @Deprecated public TblColRef makeFakeColumn(String name) { @@ -81,13 +81,13 @@ public class TableRef implements Serializable{ colDesc.setTable(table); return new TblColRef(this, colDesc); } - + // for test only @Deprecated public TblColRef makeFakeColumn(ColumnDesc colDesc) { return new TblColRef(this, colDesc); } - + @Override public boolean equals(Object o) { if (this == o) http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java index 4661bc9..da62a75 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java @@ -56,7 +56,7 @@ public class TblColRef implements Serializable { public static TblColRef newInnerColumn(String columnName, InnerDataTypeEnum dataType) { return newInnerColumn(columnName, dataType, null); } - + // used by projection rewrite, see OLAPProjectRel public static TblColRef newInnerColumn(String columnName, InnerDataTypeEnum dataType, String parserDescription) { ColumnDesc column = new ColumnDesc(); @@ -68,25 +68,25 @@ public class TblColRef implements Serializable { colRef.parserDescription = parserDescription; return colRef; } - + private static final DataModelDesc UNKNOWN_MODEL = new DataModelDesc(); static { UNKNOWN_MODEL.setName("UNKNOWN_MODEL"); } - + public static TableRef tableForUnknownModel(String tempTableAlias, TableDesc table) { return new TableRef(UNKNOWN_MODEL, tempTableAlias, table); } - + public static TblColRef columnForUnknownModel(TableRef table, ColumnDesc colDesc) { checkArgument(table.getModel() == UNKNOWN_MODEL); return new TblColRef(table, colDesc); } - + public static void fixUnknownModel(DataModelDesc model, String alias, TblColRef col) { checkArgument(col.table.getModel() == UNKNOWN_MODEL || col.table.getModel() == model); TableRef tableRef = model.findTable(alias); - checkArgument(tableRef.getTableDesc() == col.column.getTable()); + checkArgument(tableRef.getTableDesc().getIdentity().equals(col.column.getTable().getIdentity())); col.table = tableRef; col.identity = null; } @@ -101,7 +101,7 @@ public class TblColRef implements Serializable { desc.init(table); return new TblColRef(desc); } - + // ============================================================================ private TableRef table; @@ -112,13 +112,13 @@ public class TblColRef implements Serializable { TblColRef(ColumnDesc column) { this.column = column; } - + TblColRef(TableRef table, ColumnDesc column) { - checkArgument(table.getTableDesc() == column.getTable()); + checkArgument(table.getTableDesc().getIdentity().equals(column.getTable().getIdentity())); this.table = table; this.column = column; } - + public ColumnDesc getColumnDesc() { return column; } @@ -130,15 +130,23 @@ public class TblColRef implements Serializable { public TableRef getTableRef() { return table; } - + public boolean isQualified() { return table != null; } - + public String getTableAlias() { return table != null ? table.getAlias() : "UNKNOWN_ALIAS"; } - + + public String getExpressionInSourceDB() { + if (!column.isComputedColumnn()) { + return getIdentity(); + } else { + return column.getComputedColumnExpr(getTableAlias(), table.getTableIdentity()); + } + } + public String getTable() { if (column.getTable() == null) { return null; @@ -207,7 +215,7 @@ public class TblColRef implements Serializable { public String toString() { if (isInnerColumn() && parserDescription != null) return parserDescription; - + String alias = table == null ? "UNKNOWN_MODEL" : table.getAlias(); String tableName = column.getTable() == null ? "NULL" : column.getTable().getName(); String tableIdentity = column.getTable() == null ? "NULL" : column.getTable().getIdentity(); http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java index 63188a1..deac12d 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java @@ -242,10 +242,15 @@ class ProjectL2Cache { logger.error("Realization '" + realization.getCanonicalName() + "' reports column '" + col.getCanonicalName() + "', but its table is not found by MetadataManager"); return false; } - ColumnDesc foundCol = table.findColumnByName(col.getName()); - if (col.getColumnDesc().equals(foundCol) == false) { - logger.error("Realization '" + realization.getCanonicalName() + "' reports column '" + col.getCanonicalName() + "', but it is not equal to '" + foundCol + "' according to MetadataManager"); - return false; + + if (!col.getColumnDesc().isComputedColumnn()) { + ColumnDesc foundCol = table.findColumnByName(col.getName()); + if (col.getColumnDesc().equals(foundCol) == false) { + logger.error("Realization '" + realization.getCanonicalName() + "' reports column '" + col.getCanonicalName() + "', but it is not equal to '" + foundCol + "' according to MetadataManager"); + return false; + } + } else { + //computed column may not exit here } // auto-define table required by realization for some legacy test case http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/core-metadata/src/test/java/org/apache/kylin/metadata/model/DataModelDescTest.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/test/java/org/apache/kylin/metadata/model/DataModelDescTest.java b/core-metadata/src/test/java/org/apache/kylin/metadata/model/DataModelDescTest.java index b319423..f6d6fc3 100644 --- a/core-metadata/src/test/java/org/apache/kylin/metadata/model/DataModelDescTest.java +++ b/core-metadata/src/test/java/org/apache/kylin/metadata/model/DataModelDescTest.java @@ -19,6 +19,7 @@ package org.apache.kylin.metadata.model; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import org.apache.commons.lang.ArrayUtils; @@ -41,7 +42,19 @@ public class DataModelDescTest extends LocalFileMetadataTestCase { public void after() throws Exception { this.cleanupTestMetadata(); } - + + @Test + public void loadInnerModel() { + DataModelDesc model = MetadataManager.getInstance(getTestConfig()).getDataModelDesc("ci_inner_join_model"); + assertNotNull(model); + } + + @Test + public void loadLeftModel() { + DataModelDesc model = MetadataManager.getInstance(getTestConfig()).getDataModelDesc("ci_left_join_model"); + assertNotNull(model); + } + @Test public void testNoDupColInDimAndMeasure() { DataModelDesc model = MetadataManager.getInstance(getTestConfig()).getDataModelDesc("test_kylin_inner_join_model_desc"); http://git-wip-us.apache.org/repos/asf/kylin/blob/9a812d5f/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json b/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json index cfaadac..3747af8 100644 --- a/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json +++ b/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json @@ -1,445 +1,615 @@ { - "uuid" : "3819ad72-3929-4dff-b59d-cd89a01238af", - "name" : "ci_inner_join_cube", - "model_name" : "ci_inner_join_model", - "description" : null, - "dimensions" : [ { - "name" : "CAL_DT", - "table" : "TEST_CAL_DT", - "column" : "{FK}", - "derived" : [ "WEEK_BEG_DT" ] - }, { - "name" : "ORDER_ID", - "table" : "TEST_KYLIN_FACT", - "column" : "ORDER_ID" - }, { - "name" : "TEST_DATE_ENC", - "table" : "TEST_ORDER", - "column" : "TEST_DATE_ENC" - }, { - "name" : "TEST_TIME_ENC", - "table" : "TEST_ORDER", - "column" : "TEST_TIME_ENC" - }, { - "name" : "CATEGORY", - "table" : "TEST_CATEGORY_GROUPINGS", - "column" : "{FK}", - "derived" : [ "USER_DEFINED_FIELD1", "USER_DEFINED_FIELD3", "UPD_DATE", "UPD_USER" ] - }, { - "name" : "CATEGORY_HIERARCHY", - "table" : "TEST_CATEGORY_GROUPINGS", - "column" : "META_CATEG_NAME", - "derived" : null - }, { - "name" : "CATEGORY_HIERARCHY", - "table" : "TEST_CATEGORY_GROUPINGS", - "column" : "CATEG_LVL2_NAME", - "derived" : null - }, { - "name" : "CATEGORY_HIERARCHY", - "table" : "TEST_CATEGORY_GROUPINGS", - "column" : "CATEG_LVL3_NAME", - "derived" : null - }, { - "name" : "LSTG_FORMAT_NAME", - "table" : "TEST_KYLIN_FACT", - "column" : "LSTG_FORMAT_NAME", - "derived" : null - }, { - "name" : "SITE_ID", - "table" : "TEST_SITES", - "column" : "{FK}", - "derived" : [ "SITE_NAME", "CRE_USER" ] - }, { - "name" : "SELLER_TYPE_CD", - "table" : "TEST_SELLER_TYPE_DIM", - "column" : "{FK}", - "derived" : [ "SELLER_TYPE_DESC" ] - }, { - "name" : "SELLER_ID", - "table" : "TEST_KYLIN_FACT", - "column" : "SELLER_ID" - }, { - "name" : "SELLER_BUYER_LEVEL", - "table" : "SELLER_ACCOUNT", - "column" : "ACCOUNT_BUYER_LEVEL" - }, { - "name" : "SELLER_SELLER_LEVEL", - "table" : "SELLER_ACCOUNT", - "column" : "ACCOUNT_SELLER_LEVEL" - }, { - "name" : "SELLER_COUNTRY", - "table" : "SELLER_ACCOUNT", - "column" : "ACCOUNT_COUNTRY" - }, { - "name" : "SELLER_COUNTRY_NAME", - "table" : "SELLER_COUNTRY", - "column" : "NAME" - }, { - "name" : "BUYER_ID", - "table" : "TEST_ORDER", - "column" : "BUYER_ID" - }, { - "name" : "BUYER_BUYER_LEVEL", - "table" : "BUYER_ACCOUNT", - "column" : "ACCOUNT_BUYER_LEVEL" - }, { - "name" : "BUYER_SELLER_LEVEL", - "table" : "BUYER_ACCOUNT", - "column" : "ACCOUNT_SELLER_LEVEL" - }, { - "name" : "BUYER_COUNTRY", - "table" : "BUYER_ACCOUNT", - "column" : "ACCOUNT_COUNTRY" - }, { - "name" : "BUYER_COUNTRY_NAME", - "table" : "BUYER_COUNTRY", - "column" : "NAME" - } ], - "measures" : [ { - "name" : "TRANS_CNT", - "function" : { - "expression" : "COUNT", - "parameter" : { - "type" : "constant", - "value" : "1" - }, - "returntype" : "bigint" + "uuid": "3819ad72-3929-4dff-b59d-cd89a01238af", + "name": "ci_inner_join_cube", + "model_name": "ci_inner_join_model", + "description": null, + "dimensions": [ + { + "name": "CAL_DT", + "table": "TEST_CAL_DT", + "column": "{FK}", + "derived": [ + "WEEK_BEG_DT" + ] + }, + { + "name": "ORDER_ID", + "table": "TEST_KYLIN_FACT", + "column": "ORDER_ID" + }, + { + "name": "TEST_DATE_ENC", + "table": "TEST_ORDER", + "column": "TEST_DATE_ENC" + }, + { + "name": "TEST_TIME_ENC", + "table": "TEST_ORDER", + "column": "TEST_TIME_ENC" + }, + { + "name": "CATEGORY", + "table": "TEST_CATEGORY_GROUPINGS", + "column": "{FK}", + "derived": [ + "USER_DEFINED_FIELD1", + "USER_DEFINED_FIELD3", + "UPD_DATE", + "UPD_USER" + ] + }, + { + "name": "CATEGORY_HIERARCHY", + "table": "TEST_CATEGORY_GROUPINGS", + "column": "META_CATEG_NAME", + "derived": null + }, + { + "name": "CATEGORY_HIERARCHY", + "table": "TEST_CATEGORY_GROUPINGS", + "column": "CATEG_LVL2_NAME", + "derived": null + }, + { + "name": "CATEGORY_HIERARCHY", + "table": "TEST_CATEGORY_GROUPINGS", + "column": "CATEG_LVL3_NAME", + "derived": null + }, + { + "name": "LSTG_FORMAT_NAME", + "table": "TEST_KYLIN_FACT", + "column": "LSTG_FORMAT_NAME", + "derived": null + }, + { + "name": "SITE_ID", + "table": "TEST_SITES", + "column": "{FK}", + "derived": [ + "SITE_NAME", + "CRE_USER" + ] + }, + { + "name": "SELLER_TYPE_CD", + "table": "TEST_SELLER_TYPE_DIM", + "column": "{FK}", + "derived": [ + "SELLER_TYPE_DESC" + ] + }, + { + "name": "SELLER_ID", + "table": "TEST_KYLIN_FACT", + "column": "SELLER_ID" + }, + { + "name": "SELLER_BUYER_LEVEL", + "table": "SELLER_ACCOUNT", + "column": "ACCOUNT_BUYER_LEVEL" + }, + { + "name": "SELLER_SELLER_LEVEL", + "table": "SELLER_ACCOUNT", + "column": "ACCOUNT_SELLER_LEVEL" + }, + { + "name": "SELLER_COUNTRY", + "table": "SELLER_ACCOUNT", + "column": "ACCOUNT_COUNTRY" + }, + { + "name": "SELLER_COUNTRY_NAME", + "table": "SELLER_COUNTRY", + "column": "NAME" + }, + { + "name": "BUYER_ID", + "table": "TEST_ORDER", + "column": "BUYER_ID" + }, + { + "name": "BUYER_BUYER_LEVEL", + "table": "BUYER_ACCOUNT", + "column": "ACCOUNT_BUYER_LEVEL" + }, + { + "name": "BUYER_SELLER_LEVEL", + "table": "BUYER_ACCOUNT", + "column": "ACCOUNT_SELLER_LEVEL" + }, + { + "name": "BUYER_COUNTRY", + "table": "BUYER_ACCOUNT", + "column": "ACCOUNT_COUNTRY" + }, + { + "name": "DEAL_YEAR", + "table": "TEST_KYLIN_FACT", + "column": "DEAL_YEAR" + }, + { + "name": "SELLER_COUNTRY_ABBR", + "table": "SELLER_ACCOUNT", + "column": "COUNTRY_ABBR" + }, + { + "name": "BUYER_COUNTRY_ABBR", + "table": "BUYER_ACCOUNT", + "column": "COUNTRY_ABBR" + }, + { + "name": "BUYER_COUNTRY_NAME", + "table": "BUYER_COUNTRY", + "column": "NAME" } - }, { - "name" : "ITEM_COUNT_SUM", - "function" : { - "expression" : "SUM", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.ITEM_COUNT" - }, - "returntype" : "bigint" + ], + "measures": [ + { + "name": "TRANS_CNT", + "function": { + "expression": "COUNT", + "parameter": { + "type": "constant", + "value": "1" + }, + "returntype": "bigint" + } + }, + { + "name": "ITEM_COUNT_SUM", + "function": { + "expression": "SUM", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.ITEM_COUNT" + }, + "returntype": "bigint" + } + }, + { + "name": "GMV_SUM", + "function": { + "expression": "SUM", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.PRICE" + }, + "returntype": "decimal(19,4)" + } + }, + { + "name": "GMV_MIN", + "function": { + "expression": "MIN", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.PRICE" + }, + "returntype": "decimal(19,4)" + } + }, + { + "name": "GMV_MAX", + "function": { + "expression": "MAX", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.PRICE" + }, + "returntype": "decimal(19,4)" + } + }, + { + "name": "SELLER_HLL", + "function": { + "expression": "COUNT_DISTINCT", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.SELLER_ID" + }, + "returntype": "hllc(10)" + } + }, + { + "name": "SELLER_FORMAT_HLL", + "function": { + "expression": "COUNT_DISTINCT", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", + "next_parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.SELLER_ID" + } + }, + "returntype": "hllc(10)" + } + }, + { + "name": "TOP_SELLER", + "function": { + "expression": "TOP_N", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.PRICE", + "next_parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.SELLER_ID" + } + }, + "returntype": "topn(100, 4)", + "configuration": { + "topn.encoding.TEST_KYLIN_FACT.SELLER_ID": "int:4" + } + } + }, + { + "name": "TEST_COUNT_DISTINCT_BITMAP", + "function": { + "expression": "COUNT_DISTINCT", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.TEST_COUNT_DISTINCT_BITMAP" + }, + "returntype": "bitmap" + } + }, + { + "name": "TEST_EXTENDED_COLUMN", + "function": { + "expression": "EXTENDED_COLUMN", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.ORDER_ID", + "next_parameter": { + "type": "column", + "value": "TEST_ORDER.TEST_EXTENDED_COLUMN" + } + }, + "returntype": "extendedcolumn(100)" + } + }, + { + "name": "BUYER_CONTACT", + "function": { + "expression": "EXTENDED_COLUMN", + "parameter": { + "type": "column", + "value": "TEST_ORDER.BUYER_ID", + "next_parameter": { + "type": "column", + "value": "BUYER_ACCOUNT.ACCOUNT_CONTACT" + } + }, + "returntype": "extendedcolumn(100)" + } + }, + { + "name": "SELLER_CONTACT", + "function": { + "expression": "EXTENDED_COLUMN", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.SELLER_ID", + "next_parameter": { + "type": "column", + "value": "SELLER_ACCOUNT.ACCOUNT_CONTACT" + } + }, + "returntype": "extendedcolumn(100)" + } + }, + { + "name": "TRANS_ID_RAW", + "function": { + "expression": "RAW", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.TRANS_ID" + }, + "returntype": "raw" + } + }, + { + "name": "PRICE_RAW", + "function": { + "expression": "RAW", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.PRICE" + }, + "returntype": "raw" + } + }, + { + "name": "CAL_DT_RAW", + "function": { + "expression": "RAW", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.CAL_DT" + }, + "returntype": "raw" + } + }, + { + "name": "COMPUTED_COLUMN_MEASURE", + "function": { + "expression": "SUM", + "parameter": { + "type": "column", + "value": "TEST_KYLIN_FACT.DEAL_AMOUNT" + }, + "returntype": "decimal" + } } - }, { - "name" : "GMV_SUM", - "function" : { - "expression" : "SUM", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.PRICE" - }, - "returntype" : "decimal(19,4)" + ], + "dictionaries": [ + { + "column": "TEST_KYLIN_FACT.TEST_COUNT_DISTINCT_BITMAP", + "builder": "org.apache.kylin.dict.GlobalDictionaryBuilder" } - }, { - "name" : "GMV_MIN", - "function" : { - "expression" : "MIN", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.PRICE" + ], + "rowkey": { + "rowkey_columns": [ + { + "column": "TEST_KYLIN_FACT.SELLER_ID", + "encoding": "int:4" }, - "returntype" : "decimal(19,4)" - } - }, { - "name" : "GMV_MAX", - "function" : { - "expression" : "MAX", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.PRICE" + { + "column": "TEST_KYLIN_FACT.ORDER_ID", + "encoding": "int:4" }, - "returntype" : "decimal(19,4)" - } - }, { - "name" : "SELLER_HLL", - "function" : { - "expression" : "COUNT_DISTINCT", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.SELLER_ID" + { + "column": "TEST_KYLIN_FACT.CAL_DT", + "encoding": "dict" }, - "returntype" : "hllc(10)" - } - }, { - "name" : "SELLER_FORMAT_HLL", - "function" : { - "expression" : "COUNT_DISTINCT", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", - "next_parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.SELLER_ID" - } + { + "column": "TEST_KYLIN_FACT.LEAF_CATEG_ID", + "encoding": "dict" }, - "returntype" : "hllc(10)" - } - }, { - "name" : "TOP_SELLER", - "function" : { - "expression" : "TOP_N", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.PRICE", - "next_parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.SELLER_ID" - } + { + "column": "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", + "encoding": "dict" }, - "returntype" : "topn(100, 4)", - "configuration": {"topn.encoding.TEST_KYLIN_FACT.SELLER_ID" : "int:4"} - } - }, { - "name" : "TEST_COUNT_DISTINCT_BITMAP", - "function" : { - "expression" : "COUNT_DISTINCT", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.TEST_COUNT_DISTINCT_BITMAP" + { + "column": "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", + "encoding": "dict" }, - "returntype" : "bitmap" - } - }, { - "name" : "TEST_EXTENDED_COLUMN", - "function" : { - "expression" : "EXTENDED_COLUMN", - "parameter": { - "type": "column", - "value": "TEST_KYLIN_FACT.ORDER_ID", - "next_parameter": { - "type": "column", - "value": "TEST_ORDER.TEST_EXTENDED_COLUMN" - } + { + "column": "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", + "encoding": "dict" }, - "returntype": "extendedcolumn(100)" - } - }, { - "name" : "BUYER_CONTACT", - "function" : { - "expression" : "EXTENDED_COLUMN", - "parameter": { - "type": "column", - "value": "TEST_ORDER.BUYER_ID", - "next_parameter": { - "type": "column", - "value": "BUYER_ACCOUNT.ACCOUNT_CONTACT" - } + { + "column": "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", + "encoding": "fixed_length:12" }, - "returntype": "extendedcolumn(100)" - } - }, { - "name" : "SELLER_CONTACT", - "function" : { - "expression" : "EXTENDED_COLUMN", - "parameter": { - "type": "column", - "value": "TEST_KYLIN_FACT.SELLER_ID", - "next_parameter": { - "type": "column", - "value": "SELLER_ACCOUNT.ACCOUNT_CONTACT" - } + { + "column": "TEST_KYLIN_FACT.LSTG_SITE_ID", + "encoding": "dict" }, - "returntype": "extendedcolumn(100)" - } - }, { - "name" : "TRANS_ID_RAW", - "function" : { - "expression" : "RAW", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.TRANS_ID" + { + "column": "TEST_KYLIN_FACT.SLR_SEGMENT_CD", + "encoding": "dict" }, - "returntype" : "raw" - } - }, { - "name" : "PRICE_RAW", - "function" : { - "expression" : "RAW", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.PRICE" + { + "column": "TEST_ORDER.TEST_TIME_ENC", + "encoding": "time" }, - "returntype" : "raw" - } - }, { - "name" : "CAL_DT_RAW", - "function" : { - "expression" : "RAW", - "parameter" : { - "type" : "column", - "value" : "TEST_KYLIN_FACT.CAL_DT" + { + "column": "TEST_ORDER.TEST_DATE_ENC", + "encoding": "date" }, - "returntype" : "raw" - } - } ], - "dictionaries": [ { - "column": "TEST_KYLIN_FACT.TEST_COUNT_DISTINCT_BITMAP", - "builder": "org.apache.kylin.dict.GlobalDictionaryBuilder" - } ], - "rowkey" : { - "rowkey_columns" : [ { - "column" : "TEST_KYLIN_FACT.SELLER_ID", - "encoding" : "int:4" - }, { - "column" : "TEST_KYLIN_FACT.ORDER_ID", - "encoding" : "int:4" - }, { - "column" : "TEST_KYLIN_FACT.CAL_DT", - "encoding" : "dict" - }, { - "column" : "TEST_KYLIN_FACT.LEAF_CATEG_ID", - "encoding" : "dict" - }, { - "column" : "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", - "encoding" : "dict" - }, { - "column" : "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", - "encoding" : "dict" - }, { - "column" : "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", - "encoding" : "dict" - }, { - "column" : "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", - "encoding" : "fixed_length:12" - }, { - "column" : "TEST_KYLIN_FACT.LSTG_SITE_ID", - "encoding" : "dict" - }, { - "column" : "TEST_KYLIN_FACT.SLR_SEGMENT_CD", - "encoding" : "dict" - }, { - "column" : "TEST_ORDER.TEST_TIME_ENC", - "encoding" : "time" - }, { - "column" : "TEST_ORDER.TEST_DATE_ENC", - "encoding" : "date" - }, { - "column" : "TEST_ORDER.BUYER_ID", - "encoding" : "int:4" - }, { - "column" : "BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL", - "encoding" : "dict" - }, { - "column" : "BUYER_ACCOUNT.ACCOUNT_SELLER_LEVEL", - "encoding" : "dict" - }, { - "column" : "BUYER_ACCOUNT.ACCOUNT_COUNTRY", - "encoding" : "dict" - }, { - "column" : "BUYER_COUNTRY.NAME", - "encoding" : "dict" - }, { - "column" : "SELLER_ACCOUNT.ACCOUNT_BUYER_LEVEL", - "encoding" : "dict" - }, { - "column" : "SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL", - "encoding" : "dict" - }, { - "column" : "SELLER_ACCOUNT.ACCOUNT_COUNTRY", - "encoding" : "dict" - }, { - "column" : "SELLER_COUNTRY.NAME", - "encoding" : "dict" - } ] + { + "column": "TEST_ORDER.BUYER_ID", + "encoding": "int:4" + }, + { + "column": "BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL", + "encoding": "dict" + }, + { + "column": "BUYER_ACCOUNT.ACCOUNT_SELLER_LEVEL", + "encoding": "dict" + }, + { + "column": "BUYER_ACCOUNT.ACCOUNT_COUNTRY", + "encoding": "dict" + }, + { + "column": "BUYER_COUNTRY.NAME", + "encoding": "dict" + }, + { + "column": "SELLER_ACCOUNT.ACCOUNT_BUYER_LEVEL", + "encoding": "dict" + }, + { + "column": "SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL", + "encoding": "dict" + }, + { + "column": "SELLER_ACCOUNT.ACCOUNT_COUNTRY", + "encoding": "dict" + }, + { + "column": "TEST_KYLIN_FACT.DEAL_YEAR", + "encoding": "int:2" + }, + { + "column": "SELLER_COUNTRY.NAME", + "encoding": "dict" + }, + { + "column": "SELLER_ACCOUNT.COUNTRY_ABBR", + "encoding": "dict" + }, + { + "column": "BUYER_ACCOUNT.COUNTRY_ABBR", + "encoding": "dict" + } + ] }, - "signature" : null, - "last_modified" : 1448959801311, - "null_string" : null, - "hbase_mapping" : { - "column_family" : [ { - "name" : "f1", - "columns" : [ { - "qualifier" : "m", - "measure_refs" : [ "TRANS_CNT", "ITEM_COUNT_SUM", "GMV_SUM", "GMV_MIN", "GMV_MAX" ] - } ] - }, { - "name" : "f2", - "columns" : [ { - "qualifier" : "m", - "measure_refs" : [ "SELLER_HLL", "SELLER_FORMAT_HLL", "TOP_SELLER", "TEST_COUNT_DISTINCT_BITMAP" ] - } ] - }, { - "name" : "f3", - "columns" : [ { - "qualifier" : "m", - "measure_refs" : [ "TEST_EXTENDED_COLUMN", "TRANS_ID_RAW", "PRICE_RAW", "CAL_DT_RAW", "BUYER_CONTACT", "SELLER_CONTACT" ] - } ] - } ] + "signature": null, + "last_modified": 1448959801311, + "null_string": null, + "hbase_mapping": { + "column_family": [ + { + "name": "f1", + "columns": [ + { + "qualifier": "m", + "measure_refs": [ + "TRANS_CNT", + "ITEM_COUNT_SUM", + "GMV_SUM", + "GMV_MIN", + "GMV_MAX", + "COMPUTED_COLUMN_MEASURE" + ] + } + ] + }, + { + "name": "f2", + "columns": [ + { + "qualifier": "m", + "measure_refs": [ + "SELLER_HLL", + "SELLER_FORMAT_HLL", + "TOP_SELLER", + "TEST_COUNT_DISTINCT_BITMAP" + ] + } + ] + }, + { + "name": "f3", + "columns": [ + { + "qualifier": "m", + "measure_refs": [ + "TEST_EXTENDED_COLUMN", + "TRANS_ID_RAW", + "PRICE_RAW", + "CAL_DT_RAW", + "BUYER_CONTACT", + "SELLER_CONTACT" + ] + } + ] + } + ] }, - "aggregation_groups" : [ { - "includes" : [ "TEST_KYLIN_FACT.CAL_DT", - "TEST_KYLIN_FACT.LEAF_CATEG_ID", - "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", - "TEST_KYLIN_FACT.LSTG_SITE_ID", - "TEST_KYLIN_FACT.SLR_SEGMENT_CD", - "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME" ], - "select_rule" : { - "hierarchy_dims" : [ [ "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", - "TEST_KYLIN_FACT.LEAF_CATEG_ID" ] ], - "mandatory_dims" : [ ], - "joint_dims" : [ [ "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", - "TEST_KYLIN_FACT.LSTG_SITE_ID", - "TEST_KYLIN_FACT.SLR_SEGMENT_CD" ] ] - } - }, { - "includes" : [ "TEST_KYLIN_FACT.CAL_DT", - "TEST_KYLIN_FACT.LEAF_CATEG_ID", - "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", - "TEST_KYLIN_FACT.LSTG_SITE_ID", - "TEST_KYLIN_FACT.SLR_SEGMENT_CD", - "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", - - "TEST_KYLIN_FACT.SELLER_ID", - "SELLER_ACCOUNT.ACCOUNT_BUYER_LEVEL", - "SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL", - "SELLER_ACCOUNT.ACCOUNT_COUNTRY", - "SELLER_COUNTRY.NAME", - - "TEST_KYLIN_FACT.ORDER_ID", - "TEST_ORDER.TEST_DATE_ENC", - "TEST_ORDER.TEST_TIME_ENC", - "TEST_ORDER.BUYER_ID", - "BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL", - "BUYER_ACCOUNT.ACCOUNT_SELLER_LEVEL", - "BUYER_ACCOUNT.ACCOUNT_COUNTRY", - "BUYER_COUNTRY.NAME" ], - "select_rule" : { - "hierarchy_dims" : [ ], - "mandatory_dims" : [ "TEST_KYLIN_FACT.CAL_DT" ], - - "joint_dims" : [ [ "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", - "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", - "TEST_KYLIN_FACT.LEAF_CATEG_ID" ], - - [ "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", - "TEST_KYLIN_FACT.LSTG_SITE_ID", - "TEST_KYLIN_FACT.SLR_SEGMENT_CD" ], - - [ "TEST_KYLIN_FACT.SELLER_ID", - "SELLER_ACCOUNT.ACCOUNT_BUYER_LEVEL", - "SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL", - "SELLER_ACCOUNT.ACCOUNT_COUNTRY", - "SELLER_COUNTRY.NAME" ], - - [ "TEST_KYLIN_FACT.ORDER_ID", - "TEST_ORDER.TEST_DATE_ENC", - "TEST_ORDER.TEST_TIME_ENC", - "TEST_ORDER.BUYER_ID", - "BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL", - "BUYER_ACCOUNT.ACCOUNT_SELLER_LEVEL", - "BUYER_ACCOUNT.ACCOUNT_COUNTRY", - "BUYER_COUNTRY.NAME" ] ] + "aggregation_groups": [ + { + "includes": [ + "TEST_KYLIN_FACT.CAL_DT", + "TEST_KYLIN_FACT.LEAF_CATEG_ID", + "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", + "TEST_KYLIN_FACT.LSTG_SITE_ID", + "TEST_KYLIN_FACT.SLR_SEGMENT_CD", + "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", + "TEST_KYLIN_FACT.DEAL_YEAR" + ], + "select_rule": { + "hierarchy_dims": [ + [ + "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", + "TEST_KYLIN_FACT.LEAF_CATEG_ID" + ] + ], + "mandatory_dims": [], + "joint_dims": [ + [ + "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", + "TEST_KYLIN_FACT.LSTG_SITE_ID", + "TEST_KYLIN_FACT.SLR_SEGMENT_CD", + "TEST_KYLIN_FACT.DEAL_YEAR" + ] + ] + } + }, + { + "includes": [ + "TEST_KYLIN_FACT.CAL_DT", + "TEST_KYLIN_FACT.LEAF_CATEG_ID", + "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", + "TEST_KYLIN_FACT.LSTG_SITE_ID", + "TEST_KYLIN_FACT.SLR_SEGMENT_CD", + "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", + "TEST_KYLIN_FACT.SELLER_ID", + "SELLER_ACCOUNT.ACCOUNT_BUYER_LEVEL", + "SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL", + "SELLER_ACCOUNT.ACCOUNT_COUNTRY", + "SELLER_COUNTRY.NAME", + "TEST_KYLIN_FACT.ORDER_ID", + "TEST_ORDER.TEST_DATE_ENC", + "TEST_ORDER.TEST_TIME_ENC", + "TEST_ORDER.BUYER_ID", + "BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL", + "BUYER_ACCOUNT.ACCOUNT_SELLER_LEVEL", + "BUYER_ACCOUNT.ACCOUNT_COUNTRY", + "BUYER_COUNTRY.NAME", + "SELLER_ACCOUNT.COUNTRY_ABBR", + "BUYER_ACCOUNT.COUNTRY_ABBR" + ], + "select_rule": { + "hierarchy_dims": [], + "mandatory_dims": [ + "TEST_KYLIN_FACT.CAL_DT" + ], + "joint_dims": [ + [ + "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", + "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME", + "TEST_KYLIN_FACT.LEAF_CATEG_ID" + ], + [ + "TEST_KYLIN_FACT.LSTG_FORMAT_NAME", + "TEST_KYLIN_FACT.LSTG_SITE_ID", + "TEST_KYLIN_FACT.SLR_SEGMENT_CD", + "SELLER_ACCOUNT.COUNTRY_ABBR", + "BUYER_ACCOUNT.COUNTRY_ABBR" + ], + [ + "TEST_KYLIN_FACT.SELLER_ID", + "SELLER_ACCOUNT.ACCOUNT_BUYER_LEVEL", + "SELLER_ACCOUNT.ACCOUNT_SELLER_LEVEL", + "SELLER_ACCOUNT.ACCOUNT_COUNTRY", + "SELLER_COUNTRY.NAME" + ], + [ + "TEST_KYLIN_FACT.ORDER_ID", + "TEST_ORDER.TEST_DATE_ENC", + "TEST_ORDER.TEST_TIME_ENC", + "TEST_ORDER.BUYER_ID", + "BUYER_ACCOUNT.ACCOUNT_BUYER_LEVEL", + "BUYER_ACCOUNT.ACCOUNT_SELLER_LEVEL", + "BUYER_ACCOUNT.ACCOUNT_COUNTRY", + "BUYER_COUNTRY.NAME" + ] + ] + } } - } ], - "notify_list" : null, - "status_need_notify" : [ ], - "auto_merge_time_ranges" : null, - "retention_range" : 0, - "engine_type" : 4, - "storage_type" : 2, + ], + "notify_list": null, + "status_need_notify": [], + "auto_merge_time_ranges": null, + "retention_range": 0, + "engine_type": 2, + "storage_type": 2, "override_kylin_properties": { "kylin.cube.algorithm": "LAYER" },