Repository: kylin Updated Branches: refs/heads/yang23 696f94a97 -> ca1ede72f
KYLIN-2514 handle disordered joins in data model Signed-off-by: Hongbin Ma <mahong...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/ca1ede72 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/ca1ede72 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/ca1ede72 Branch: refs/heads/yang23 Commit: ca1ede72f8844e9e9b55d11952fb4ad1b597243e Parents: 696f94a Author: Roger Shi <rogershijich...@hotmail.com> Authored: Fri Mar 17 19:27:18 2017 +0800 Committer: Hongbin Ma <mahong...@apache.org> Committed: Fri Mar 17 19:56:12 2017 +0800 ---------------------------------------------------------------------- .../apache/kylin/metadata/model/JoinsTree.java | 43 +++++++++++++++++--- .../model_desc/ci_left_join_model.json | 28 ++++++------- 2 files changed, 52 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/ca1ede72/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 c7666cb..3c876a0 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 @@ -24,8 +24,12 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Queue; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Queues; public class JoinsTree implements Serializable { private static final long serialVersionUID = 1L; @@ -40,12 +44,41 @@ public class JoinsTree implements Serializable { Preconditions.checkState(col.isQualified()); } - tableChains.put(rootTable.getAlias(), new Chain(rootTable, null, null)); + // Walk through joins to build FK table to joins mapping + HashMap<String, List<JoinDesc>> fkJoinMap = Maps.newHashMap(); + int joinCount = 0; + for (JoinDesc join: joins) { + joinCount++; + String fkSideAlias = join.getFKSide().getAlias(); + if (fkJoinMap.containsKey(fkSideAlias)) { + fkJoinMap.get(fkSideAlias).add(join); + } else { + List<JoinDesc> joinDescList = Lists.newArrayList(join); + fkJoinMap.put(fkSideAlias, joinDescList); + } + } - for (JoinDesc join : joins) { - TableRef pkSide = join.getPKSide(); - Chain fkSide = tableChains.get(join.getFKSide().getAlias()); - tableChains.put(pkSide.getAlias(), new Chain(pkSide, join, fkSide)); + // Width-first build tree (tableChains) + Queue<Chain> chainBuff = Queues.newArrayDeque(); + chainBuff.add(new Chain(rootTable, null, null)); + int chainCount = 0; + while (!chainBuff.isEmpty()) { + Chain chain= chainBuff.poll(); + String pkSideAlias = chain.table.getAlias(); + chainCount++; + tableChains.put(pkSideAlias, chain); + + // this round pk side is next round's fk side + if (fkJoinMap.containsKey(pkSideAlias)) { + for (JoinDesc join: fkJoinMap.get(pkSideAlias)) { + chainBuff.add(new Chain(join.getPKSide(), join, chain)); + } + } + } + + // if join count not match (chain count - 1), there must be some join not take effect + if (joinCount != (chainCount - 1)) { + throw new IllegalArgumentException("There's some illegal Joins, please check your model"); } } http://git-wip-us.apache.org/repos/asf/kylin/blob/ca1ede72/examples/test_case_data/localmeta/model_desc/ci_left_join_model.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/model_desc/ci_left_join_model.json b/examples/test_case_data/localmeta/model_desc/ci_left_join_model.json index 1b08aaf..bc5b444 100644 --- a/examples/test_case_data/localmeta/model_desc/ci_left_join_model.json +++ b/examples/test_case_data/localmeta/model_desc/ci_left_join_model.json @@ -31,20 +31,6 @@ } }, { - "table": "DEFAULT.TEST_ACCOUNT", - "alias": "SELLER_ACCOUNT", - "kind": "FACT", - "join": { - "type": "LEFT", - "primary_key": [ - "SELLER_ACCOUNT.ACCOUNT_ID" - ], - "foreign_key": [ - "TEST_KYLIN_FACT.SELLER_ID" - ] - } - }, - { "table": "EDW.TEST_CAL_DT", "join": { "type": "LEFT", @@ -119,6 +105,20 @@ "SELLER_ACCOUNT.ACCOUNT_COUNTRY" ] } + }, + { + "table": "DEFAULT.TEST_ACCOUNT", + "alias": "SELLER_ACCOUNT", + "kind": "FACT", + "join": { + "type": "LEFT", + "primary_key": [ + "SELLER_ACCOUNT.ACCOUNT_ID" + ], + "foreign_key": [ + "TEST_KYLIN_FACT.SELLER_ID" + ] + } } ], "dimensions": [