You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2016/10/21 10:22:20 UTC

[3/3] kylin git commit: KYLIN-1971 refactor ModelDesc to use TableRef

KYLIN-1971 refactor ModelDesc to use TableRef


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/5156ccd4
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/5156ccd4
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/5156ccd4

Branch: refs/heads/master
Commit: 5156ccd470fe56fa8d57671a2b6262dae3fcef96
Parents: 3384124
Author: Li Yang <li...@apache.org>
Authored: Wed Sep 28 18:16:15 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Fri Oct 21 18:21:21 2016 +0800

----------------------------------------------------------------------
 .../org/apache/kylin/cube/model/CubeDesc.java   |     2 +-
 .../apache/kylin/cube/model/DictionaryDesc.java |     4 +-
 .../kylin/cube/model/v1_4_0/CubeDesc.java       |     2 +-
 .../org/apache/kylin/job/JoinedFlatTable.java   |     2 +-
 .../kylin/metadata/model/DataModelDesc.java     |   152 +-
 .../apache/kylin/metadata/model/LookupDesc.java |    25 +-
 .../apache/kylin/metadata/model/TableDesc.java  |     3 +-
 .../apache/kylin/metadata/model/TableRef.java   |   102 +
 .../apache/kylin/metadata/model/TblColRef.java  |     6 +
 .../kylin/metadata/MetadataManagerTest.java     |    16 +-
 examples/sample_cube/create_sample_tables.sql   |    19 +-
 .../sample_cube/data/DEFAULT.KYLIN_COUNTRY.csv  |   244 +
 .../sample_cube/data/DEFAULT.KYLIN_SALES.csv    | 20000 ++++++++---------
 .../template/table/DEFAULT.KYLIN_COUNTRY.json   |    24 +
 .../template/table/DEFAULT.KYLIN_SALES.json     |    26 +-
 .../test_kylin_snowflake_model_desc.json        |   161 +
 .../table/DEFAULT.TEST_KYLIN_COUNTRY.json       |    24 +
 .../table/DEFAULT.TEST_KYLIN_FACT.json          |     8 +
 .../rest/controller/CubeDescController.java     |     4 -
 19 files changed, 10736 insertions(+), 10088 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/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 bf3724a..7db460e 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
@@ -344,7 +344,7 @@ public class CubeDesc extends RootPersistentEntity implements IEngineAware {
     }
 
     public TableDesc getFactTableDesc() {
-        return model.getFactTableDesc();
+        return model.getFactTableRef().getTableDesc();
     }
 
     public List<TableDesc> getLookupTableDescs() {

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/core-cube/src/main/java/org/apache/kylin/cube/model/DictionaryDesc.java
----------------------------------------------------------------------
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/DictionaryDesc.java b/core-cube/src/main/java/org/apache/kylin/cube/model/DictionaryDesc.java
index f8e3432..f471f9f 100644
--- a/core-cube/src/main/java/org/apache/kylin/cube/model/DictionaryDesc.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/model/DictionaryDesc.java
@@ -46,11 +46,11 @@ public class DictionaryDesc {
         DataModelDesc model = cubeDesc.getModel();
 
         column = column.toUpperCase();
-        colRef = model.findColumn(column).getRef();
+        colRef = model.findColumn(column);
 
         if (reuseColumn != null) {
             reuseColumn = reuseColumn.toUpperCase();
-            reuseColRef = model.findColumn(reuseColumn).getRef();
+            reuseColRef = model.findColumn(reuseColumn);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/core-cube/src/main/java/org/apache/kylin/cube/model/v1_4_0/CubeDesc.java
----------------------------------------------------------------------
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/model/v1_4_0/CubeDesc.java b/core-cube/src/main/java/org/apache/kylin/cube/model/v1_4_0/CubeDesc.java
index 14aa5f8..760b3e7 100644
--- a/core-cube/src/main/java/org/apache/kylin/cube/model/v1_4_0/CubeDesc.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/model/v1_4_0/CubeDesc.java
@@ -329,7 +329,7 @@ public class CubeDesc extends RootPersistentEntity {
     }
 
     public TableDesc getFactTableDesc() {
-        return model.getFactTableDesc();
+        return model.getFactTableRef().getTableDesc();
     }
 
     public List<TableDesc> getLookupTableDescs() {

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/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 699d084..3cc27ba 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
@@ -227,7 +227,7 @@ public class JoinedFlatTable {
         
         List<JoinDesc> result = Lists.newArrayList();
         for (LookupDesc lookup : flatDesc.getDataModel().getLookups()) {
-            String table = lookup.getTableDesc().getIdentity();
+            String table = lookup.getTableRef().getTableIdentity();
             if (usedTableIdentities.contains(table)) {
                 result.add(lookup.getJoin());
             }

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/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 d04830b..f175d92 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
@@ -38,6 +38,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
 @SuppressWarnings("serial")
@@ -80,9 +81,11 @@ public class DataModelDesc extends RootPersistentEntity {
     @JsonProperty("capacity")
     private RealizationCapacity capacity = RealizationCapacity.MEDIUM;
 
-    private TableDesc factTableDesc;
-
-    private List<TableDesc> lookupTableDescs = Lists.newArrayList();
+    // computed attributes
+    private TableRef factTableRef;
+    private List<TableRef> lookupTableRefs = Lists.newArrayList();
+    private Map<String, TableRef> aliasMap = Maps.newHashMap(); // a table has exactly one alias
+    private Map<String, TableRef> tableNameMap = Maps.newHashMap(); // a table maybe referenced by multiple names
 
     /**
      * Error messages during resolving json metadata
@@ -129,12 +132,21 @@ public class DataModelDesc extends RootPersistentEntity {
         return factTable;
     }
 
-    public TableDesc getFactTableDesc() {
-        return factTableDesc;
+    public TableRef getFactTableRef() {
+        return factTableRef;
     }
 
+    public List<TableRef> getLookupTableRefs() {
+        return lookupTableRefs;
+    }
+    
+    @Deprecated
     public List<TableDesc> getLookupTableDescs() {
-        return lookupTableDescs;
+        List<TableDesc> result = Lists.newArrayList();
+        for (TableRef table : getLookupTableRefs()) {
+            result.add(table.getTableDesc());
+        }
+        return result;
     }
 
     public void setFactTable(String factTable) {
@@ -202,77 +214,111 @@ public class DataModelDesc extends RootPersistentEntity {
         return candidate;
     }
 
-    // TODO let this replace CubeDesc.buildColumnNameAbbreviation()
-    public ColumnDesc findColumn(String column) {
-        ColumnDesc colDesc = null;
+    public TblColRef findColumn(String table, String column) {
+        TableRef tableRef = findTable(table);
+        TblColRef result = tableRef.getColumn(column);
+        if (result == null)
+            throw new IllegalArgumentException("Column not found by " + table + "." + column);
+        return result;
+    }
+    
+    public TblColRef findColumn(String column) {
+        TblColRef result = null;
 
         int cut = column.lastIndexOf('.');
         if (cut > 0) {
             // table specified
-            String table = column.substring(0, cut);
-            TableDesc tableDesc = findTable(table);
-            colDesc = tableDesc.findColumnByName(column.substring(cut + 1));
+            result = findColumn(column.substring(0, cut), column.substring(cut + 1));
         } else {
             // table not specified, try each table
-            colDesc = factTableDesc.findColumnByName(column);
-            if (colDesc == null) {
-                for (TableDesc tableDesc : lookupTableDescs) {
-                    colDesc = tableDesc.findColumnByName(column);
-                    if (colDesc != null)
+            result = factTableRef.getColumn(column);
+            if (result == null) {
+                for (TableRef tableRef : lookupTableRefs) {
+                    result = tableRef.getColumn(column);
+                    if (result != null)
                         break;
                 }
             }
         }
 
-        if (colDesc == null)
+        if (result == null)
             throw new IllegalArgumentException("Column not found by " + column);
 
-        return colDesc;
+        return result;
     }
 
-    public TableDesc findTable(String table) {
-        if (factTableDesc.getName().equalsIgnoreCase(table) || factTableDesc.getIdentity().equalsIgnoreCase(table))
-            return factTableDesc;
-
-        for (TableDesc desc : lookupTableDescs) {
-            if (desc.getName().equalsIgnoreCase(table) || desc.getIdentity().equalsIgnoreCase(table))
-                return desc;
+    public TableRef findTable(String table) {
+        TableRef result = tableNameMap.get(table);
+        if (result == null) {
+            throw new IllegalArgumentException("Table not found by " + table);
         }
-
-        throw new IllegalArgumentException("Table not found by " + table);
+        return result;
     }
 
     public void init(KylinConfig config, Map<String, TableDesc> tables) {
         this.config = config;
-        this.factTable = this.factTable.toUpperCase();
-        this.factTableDesc = tables.get(this.factTable.toUpperCase());
-        if (factTableDesc == null) {
-            throw new IllegalStateException("Fact table does not exist:" + this.factTable);
-        }
-
+        
+        initTableAlias(tables);
         initJoinColumns(tables);
         ModelDimensionDesc.capicalizeStrings(dimensions);
         initPartitionDesc(tables);
     }
 
+    private void initTableAlias(Map<String, TableDesc> tables) {
+        factTable = factTable.toUpperCase();
+        
+        if (tables.containsKey(factTable) == false)
+            throw new IllegalStateException("Fact table does not exist:" + factTable);
+        
+        factTableRef = new TableRef(this, "FACT", tables.get(factTable));
+        addAlias(factTableRef);
+        
+        for (LookupDesc lookup : lookups) {
+            lookup.setTable(lookup.getTable().toUpperCase());
+            
+            if (tables.containsKey(lookup.getTable()) == false)
+                throw new IllegalStateException("Lookup table does not exist:" + lookup.getTable());
+            
+            TableDesc tableDesc = tables.get(lookup.getTable());
+            String alias = lookup.getAlias();
+            if (alias == null)
+                alias = tableDesc.getName();
+            TableRef ref = new TableRef(this, alias, tableDesc);
+            lookup.setTableRef(ref);
+            lookupTableRefs.add(ref);
+            addAlias(ref);
+        }
+
+        tableNameMap.putAll(aliasMap);
+    }
+
+    private void addAlias(TableRef ref) {
+        String alias = ref.getAlias();
+        if (aliasMap.containsKey(alias))
+            throw new IllegalStateException("Alias '" + alias + "' ref to multiple tables: " + ref.getTableIdentity() + ", " + aliasMap.get(alias).getTableIdentity());
+        aliasMap.put(alias, ref);
+        
+        TableDesc table = ref.getTableDesc();
+        addTableName(table.getName(), ref);
+        addTableName(table.getIdentity(), ref);
+    }
+
+    private void addTableName(String name, TableRef ref) {
+        if (tableNameMap.containsKey(name)) {
+            tableNameMap.put(name, null); // conflict name
+        } else {
+            tableNameMap.put(name, ref);
+        }
+    }
+
     private void initPartitionDesc(Map<String, TableDesc> tables) {
         if (this.partitionDesc != null)
             this.partitionDesc.init(tables);
     }
 
     private void initJoinColumns(Map<String, TableDesc> tables) {
-        // join columns may or may not present in cube;
-        // here we don't modify 'allColumns' and 'dimensionColumns';
-        // initDimensionColumns() will do the update
         for (LookupDesc lookup : this.lookups) {
-            lookup.setTable(lookup.getTable().toUpperCase());
-            TableDesc dimTable = tables.get(lookup.getTable());
-            if (dimTable == null) {
-                throw new IllegalStateException("Table " + lookup.getTable() + " does not exist for " + this);
-            }
-            lookup.setTableDesc(dimTable);
-            this.lookupTableDescs.add(dimTable);
-
+            TableRef dimTable = lookup.getTableRef();
             JoinDesc join = lookup.getJoin();
             if (join == null)
                 continue;
@@ -284,13 +330,11 @@ public class DataModelDesc extends RootPersistentEntity {
             String[] pks = join.getPrimaryKey();
             TblColRef[] pkCols = new TblColRef[pks.length];
             for (int i = 0; i < pks.length; i++) {
-                ColumnDesc col = dimTable.findColumnByName(pks[i]);
+                TblColRef col = dimTable.getColumn(pks[i]);
                 if (col == null) {
-                    throw new IllegalStateException("Can't find column " + pks[i] + " in table " + dimTable.getIdentity());
+                    throw new IllegalStateException("Can't find column " + pks[i] + " in table " + dimTable.getTableIdentity());
                 }
-                TblColRef colRef = new TblColRef(col);
-                pks[i] = colRef.getName();
-                pkCols[i] = colRef;
+                pkCols[i] = col;
             }
             join.setPrimaryKeyColumns(pkCols);
 
@@ -298,13 +342,11 @@ public class DataModelDesc extends RootPersistentEntity {
             String[] fks = join.getForeignKey();
             TblColRef[] fkCols = new TblColRef[fks.length];
             for (int i = 0; i < fks.length; i++) {
-                ColumnDesc col = factTableDesc.findColumnByName(fks[i]);
+                TblColRef col = factTableRef.getColumn(fks[i]);
                 if (col == null) {
                     throw new IllegalStateException("Can't find column " + fks[i] + " in table " + this.getFactTable());
                 }
-                TblColRef colRef = new TblColRef(col);
-                fks[i] = colRef.getName();
-                fkCols[i] = colRef;
+                fkCols[i] = col;
             }
             join.setForeignKeyColumns(fkCols);
 
@@ -314,7 +356,7 @@ public class DataModelDesc extends RootPersistentEntity {
             }
             for (int i = 0; i < fkCols.length; i++) {
                 if (!fkCols[i].getDatatype().equals(pkCols[i].getDatatype())) {
-                    logger.warn("Primary key " + lookup.getTable() + "." + pkCols[i].getName() + "." + pkCols[i].getDatatype() + " are not consistent with Foreign key " + this.getFactTable() + "." + fkCols[i].getName() + "." + fkCols[i].getDatatype());
+                    logger.warn("PK " + lookup.getTable() + "." + pkCols[i].getName() + "." + pkCols[i].getDatatype() + " are not consistent with FK " + this.getFactTable() + "." + fkCols[i].getName() + "." + fkCols[i].getDatatype());
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
index c85612a..b8828f7 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
@@ -19,6 +19,7 @@
 package org.apache.kylin.metadata.model;
 
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -28,33 +29,37 @@ public class LookupDesc {
     @JsonProperty("table")
     private String table;
 
+    @JsonProperty("alias")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String alias;
+    
     @JsonProperty("join")
     private JoinDesc join;
     
-    private TableDesc tableDesc;
+    private TableRef tableRef;
 
     public String getTable() {
         return table;
     }
 
-    public void setTable(String table) {
+    void setTable(String table) {
         this.table = table;
     }
 
+    public String getAlias() {
+        return alias;
+    }
+    
     public JoinDesc getJoin() {
         return join;
     }
 
-    public void setJoin(JoinDesc join) {
-        this.join = join;
+    public TableRef getTableRef() {
+        return tableRef;
     }
 
-    public TableDesc getTableDesc() {
-        return tableDesc;
-    }
-
-    void setTableDesc(TableDesc tableDesc) {
-        this.tableDesc = tableDesc;
+    void setTableRef(TableRef ref) {
+        this.tableRef = ref;
     }
     
     

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/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 e163d1d..659de07 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
@@ -211,8 +211,7 @@ public class TableDesc extends RootPersistentEntity implements ISourceAware {
             return false;
         if (!Arrays.equals(columns, tableDesc.columns))
             return false;
-        //        if (tableType != null ? !tableType.equals(tableDesc.tableType) : tableDesc.tableType != null)
-        //            return false;
+        
         return getIdentity().equals(tableDesc.getIdentity());
 
     }

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/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
new file mode 100644
index 0000000..626fb16
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableRef.java
@@ -0,0 +1,102 @@
+/*
+ * 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.util.Map;
+
+import com.google.common.collect.Maps;
+
+public class TableRef {
+
+    final DataModelDesc model;
+    final String alias;
+    final TableDesc table;
+    final Map<String, TblColRef> columns;
+
+    TableRef(DataModelDesc model, String alias, TableDesc table) {
+        this.model = model;
+        this.alias = alias;
+        this.table = table;
+        this.columns = Maps.newLinkedHashMap();
+        
+        for (ColumnDesc col : table.getColumns()) {
+            columns.put(col.getName(), new TblColRef(this, col));
+        }
+    }
+
+    public DataModelDesc getModel() {
+        return model;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public TableDesc getTableDesc() {
+        return table;
+    }
+
+    public String getTableName() {
+        return table.getName();
+    }
+
+    public String getTableIdentity() {
+        return table.getIdentity();
+    }
+
+    public TblColRef getColumn(String name) {
+        return columns.get(name);
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        TableRef t = (TableRef) o;
+
+        if (!model.equals(t.model))
+            return false;
+        if (!alias.equals(t.alias))
+            return false;
+        if (!table.getIdentity().equals(t.table.getIdentity()))
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 0;
+        result = 31 * result + model.getName().hashCode();
+        result = 31 * result + alias.hashCode();
+        result = 31 * result + table.getIdentity().hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        if (alias.equals(table.getName()))
+            return "TableRef[" + table.getName() + "]";
+        else
+            return "TableRef[" + alias + ":" + table.getName() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/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 2764747..0f3f70d 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
@@ -63,11 +63,17 @@ public class TblColRef implements Serializable {
 
     // ============================================================================
 
+    private TableRef table;
     private ColumnDesc column;
 
     TblColRef(ColumnDesc column) {
         this.column = column;
     }
+    
+    TblColRef(TableRef table, ColumnDesc column) {
+        this.table = table;
+        this.column = column;
+    }
 
     public ColumnDesc getColumnDesc() {
         return column;

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/core-metadata/src/test/java/org/apache/kylin/metadata/MetadataManagerTest.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/test/java/org/apache/kylin/metadata/MetadataManagerTest.java b/core-metadata/src/test/java/org/apache/kylin/metadata/MetadataManagerTest.java
index a4977c4..5f215f1 100644
--- a/core-metadata/src/test/java/org/apache/kylin/metadata/MetadataManagerTest.java
+++ b/core-metadata/src/test/java/org/apache/kylin/metadata/MetadataManagerTest.java
@@ -68,7 +68,21 @@ public class MetadataManagerTest extends LocalFileMetadataTestCase {
     @Test
     public void testDataModel() throws Exception {
         DataModelDesc modelDesc = getInstance(getTestConfig()).getDataModelDesc("test_kylin_left_join_model_desc");
-
         Assert.assertTrue(modelDesc.getDimensions().size() > 0);
     }
+    
+    @Test
+    public void testSnowflakeDataModel() throws Exception {
+        DataModelDesc model = getInstance(getTestConfig()).getDataModelDesc("test_kylin_snowflake_model_desc");
+        Assert.assertTrue(model.getDimensions().size() > 0);
+
+        try {
+            model.findTable("TEST_KYLIN_COUNTRY");
+            Assert.fail();
+        } catch (IllegalArgumentException ex) {
+            // excepted
+        }
+        Assert.assertNotNull(model.findColumn("BUYER_COUNTRY"));
+        Assert.assertNotNull(model.findColumn("SELLER_COUNTRY"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/examples/sample_cube/create_sample_tables.sql
----------------------------------------------------------------------
diff --git a/examples/sample_cube/create_sample_tables.sql b/examples/sample_cube/create_sample_tables.sql
index 9fa17d7..2001e76 100644
--- a/examples/sample_cube/create_sample_tables.sql
+++ b/examples/sample_cube/create_sample_tables.sql
@@ -170,6 +170,18 @@ COMMENT 'Detail category inforamtion, Dimension Table'
 ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
 STORED AS TEXTFILE;
 
+DROP TABLE IF EXISTS DEFAULT.KYLIN_COUNTRY;
+
+CREATE TABLE DEFAULT.KYLIN_COUNTRY
+(
+COUNTRY string
+,LATITUDE double
+,LONGITUDE double
+,NAME string
+)
+ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
+STORED AS TEXTFILE;
+
 DROP TABLE IF EXISTS DEFAULT.KYLIN_SALES;
 
 CREATE TABLE DEFAULT.KYLIN_SALES
@@ -183,13 +195,16 @@ TRANS_ID bigint
 ,PRICE decimal(19,4) COMMENT 'Order Price'
 ,ITEM_COUNT bigint COMMENT 'Number of Purchased Goods'
 ,SELLER_ID bigint COMMENT 'Seller ID'
-,USER_ID string COMMENT 'USER ID'
-,REGION string COMMENT 'REGION'
+,BUYER_COUNTRY string 'Buyer Country'
+,SELLER_COUNTRY string 'Seller Country'
+,USER_ID string COMMENT 'System User ID'
+,REGION string COMMENT 'System User Region'
 )
 COMMENT 'Sales order table, fact table'
 ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
 STORED AS TEXTFILE;
 
 LOAD DATA INPATH '/tmp/kylin/sample_cube/data/DEFAULT.KYLIN_SALES.csv' OVERWRITE INTO TABLE DEFAULT.KYLIN_SALES;
+LOAD DATA INPATH '/tmp/kylin/sample_cube/data/DEFAULT.KYLIN_COUNTRY.csv' OVERWRITE INTO TABLE DEFAULT.KYLIN_COUNTRY;
 LOAD DATA INPATH '/tmp/kylin/sample_cube/data/DEFAULT.KYLIN_CAL_DT.csv' OVERWRITE INTO TABLE DEFAULT.KYLIN_CAL_DT;
 LOAD DATA INPATH '/tmp/kylin/sample_cube/data/DEFAULT.KYLIN_CATEGORY_GROUPINGS.csv' OVERWRITE INTO TABLE DEFAULT.KYLIN_CATEGORY_GROUPINGS;

http://git-wip-us.apache.org/repos/asf/kylin/blob/5156ccd4/examples/sample_cube/data/DEFAULT.KYLIN_COUNTRY.csv
----------------------------------------------------------------------
diff --git a/examples/sample_cube/data/DEFAULT.KYLIN_COUNTRY.csv b/examples/sample_cube/data/DEFAULT.KYLIN_COUNTRY.csv
new file mode 100644
index 0000000..aced0e3
--- /dev/null
+++ b/examples/sample_cube/data/DEFAULT.KYLIN_COUNTRY.csv
@@ -0,0 +1,244 @@
+AD,42.546245,1.601554,Andorra
+AE,23.424076,53.847818,United Arab Emirates
+AF,33.93911,67.709953,Afghanistan
+AG,17.060816,-61.796428,Antigua and Barbuda
+AI,18.220554,-63.068615,Anguilla
+AL,41.153332,20.168331,Albania
+AM,40.069099,45.038189,Armenia
+AN,12.226079,-69.060087,Netherlands Antilles
+AO,-11.202692,17.873887,Angola
+AQ,-75.250973,-0.071389,Antarctica
+AR,-38.416097,-63.616672,Argentina
+AS,-14.270972,-170.132217,American Samoa
+AT,47.516231,14.550072,Austria
+AU,-25.274398,133.775136,Australia
+AW,12.52111,-69.968338,Aruba
+AZ,40.143105,47.576927,Azerbaijan
+BA,43.915886,17.679076,Bosnia and Herzegovina
+BB,13.193887,-59.543198,Barbados
+BD,23.684994,90.356331,Bangladesh
+BE,50.503887,4.469936,Belgium
+BF,12.238333,-1.561593,Burkina Faso
+BG,42.733883,25.48583,Bulgaria
+BH,25.930414,50.637772,Bahrain
+BI,-3.373056,29.918886,Burundi
+BJ,9.30769,2.315834,Benin
+BM,32.321384,-64.75737,Bermuda
+BN,4.535277,114.727669,Brunei
+BO,-16.290154,-63.588653,Bolivia
+BR,-14.235004,-51.92528,Brazil
+BS,25.03428,-77.39628,Bahamas
+BT,27.514162,90.433601,Bhutan
+BV,-54.423199,3.413194,Bouvet Island
+BW,-22.328474,24.684866,Botswana
+BY,53.709807,27.953389,Belarus
+BZ,17.189877,-88.49765,Belize
+CA,56.130366,-106.346771,Canada
+CC,-12.164165,96.870956,Cocos [Keeling] Islands
+CD,-4.038333,21.758664,Congo [DRC]
+CF,6.611111,20.939444,Central African Republic
+CG,-0.228021,15.827659,Congo [Republic]
+CH,46.818188,8.227512,Switzerland
+CI,7.539989,-5.54708,C?te d'Ivoire
+CK,-21.236736,-159.777671,Cook Islands
+CL,-35.675147,-71.542969,Chile
+CM,7.369722,12.354722,Cameroon
+CN,35.86166,104.195397,China
+CO,4.570868,-74.297333,Colombia
+CR,9.748917,-83.753428,Costa Rica
+CU,21.521757,-77.781167,Cuba
+CV,16.002082,-24.013197,Cape Verde
+CX,-10.447525,105.690449,Christmas Island
+CY,35.126413,33.429859,Cyprus
+CZ,49.817492,15.472962,Czech Republic
+DE,51.165691,10.451526,Germany
+DJ,11.825138,42.590275,Djibouti
+DK,56.26392,9.501785,Denmark
+DM,15.414999,-61.370976,Dominica
+DO,18.735693,-70.162651,Dominican Republic
+DZ,28.033886,1.659626,Algeria
+EC,-1.831239,-78.183406,Ecuador
+EE,58.595272,25.013607,Estonia
+EG,26.820553,30.802498,Egypt
+EH,24.215527,-12.885834,Western Sahara
+ER,15.179384,39.782334,Eritrea
+ES,40.463667,-3.74922,Spain
+ET,9.145,40.489673,Ethiopia
+FI,61.92411,25.748151,Finland
+FJ,-16.578193,179.414413,Fiji
+FK,-51.796253,-59.523613,Falkland Islands [Islas Malvinas]
+FM,7.425554,150.550812,Micronesia
+FO,61.892635,-6.911806,Faroe Islands
+FR,46.227638,2.213749,France
+GA,-0.803689,11.609444,Gabon
+GB,55.378051,-3.435973,United Kingdom
+GD,12.262776,-61.604171,Grenada
+GE,42.315407,43.356892,Georgia
+GF,3.933889,-53.125782,French Guiana
+GG,49.465691,-2.585278,Guernsey
+GH,7.946527,-1.023194,Ghana
+GI,36.137741,-5.345374,Gibraltar
+GL,71.706936,-42.604303,Greenland
+GM,13.443182,-15.310139,Gambia
+GN,9.945587,-9.696645,Guinea
+GP,16.995971,-62.067641,Guadeloupe
+GQ,1.650801,10.267895,Equatorial Guinea
+GR,39.074208,21.824312,Greece
+GS,-54.429579,-36.587909,South Georgia and the South Sandwich Islands
+GT,15.783471,-90.230759,Guatemala
+GU,13.444304,144.793731,Guam
+GW,11.803749,-15.180413,Guinea-Bissau
+GY,4.860416,-58.93018,Guyana
+GZ,31.354676,34.308825,Gaza Strip
+HK,22.396428,114.109497,Hong Kong
+HM,-53.08181,73.504158,Heard Island and McDonald Islands
+HN,15.199999,-86.241905,Honduras
+HR,45.1,15.2,Croatia
+HT,18.971187,-72.285215,Haiti
+HU,47.162494,19.503304,Hungary
+ID,-0.789275,113.921327,Indonesia
+IE,53.41291,-8.24389,Ireland
+IL,31.046051,34.851612,Israel
+IM,54.236107,-4.548056,Isle of Man
+IN,20.593684,78.96288,India
+IO,-6.343194,71.876519,British Indian Ocean Territory
+IQ,33.223191,43.679291,Iraq
+IR,32.427908,53.688046,Iran
+IS,64.963051,-19.020835,Iceland
+IT,41.87194,12.56738,Italy
+JE,49.214439,-2.13125,Jersey
+JM,18.109581,-77.297508,Jamaica
+JO,30.585164,36.238414,Jordan
+JP,36.204824,138.252924,Japan
+KE,-0.023559,37.906193,Kenya
+KG,41.20438,74.766098,Kyrgyzstan
+KH,12.565679,104.990963,Cambodia
+KI,-3.370417,-168.734039,Kiribati
+KM,-11.875001,43.872219,Comoros
+KN,17.357822,-62.782998,Saint Kitts and Nevis
+KP,40.339852,127.510093,North Korea
+KR,35.907757,127.766922,South Korea
+KW,29.31166,47.481766,Kuwait
+KY,19.513469,-80.566956,Cayman Islands
+KZ,48.019573,66.923684,Kazakhstan
+LA,19.85627,102.495496,Laos
+LB,33.854721,35.862285,Lebanon
+LC,13.909444,-60.978893,Saint Lucia
+LI,47.166,9.555373,Liechtenstein
+LK,7.873054,80.771797,Sri Lanka
+LR,6.428055,-9.429499,Liberia
+LS,-29.609988,28.233608,Lesotho
+LT,55.169438,23.881275,Lithuania
+LU,49.815273,6.129583,Luxembourg
+LV,56.879635,24.603189,Latvia
+LY,26.3351,17.228331,Libya
+MA,31.791702,-7.09262,Morocco
+MC,43.750298,7.412841,Monaco
+MD,47.411631,28.369885,Moldova
+ME,42.708678,19.37439,Montenegro
+MG,-18.766947,46.869107,Madagascar
+MH,7.131474,171.184478,Marshall Islands
+MK,41.608635,21.745275,Macedonia [FYROM]
+ML,17.570692,-3.996166,Mali
+MM,21.913965,95.956223,Myanmar [Burma]
+MN,46.862496,103.846656,Mongolia
+MO,22.198745,113.543873,Macau
+MP,17.33083,145.38469,Northern Mariana Islands
+MQ,14.641528,-61.024174,Martinique
+MR,21.00789,-10.940835,Mauritania
+MS,16.742498,-62.187366,Montserrat
+MT,35.937496,14.375416,Malta
+MU,-20.348404,57.552152,Mauritius
+MV,3.202778,73.22068,Maldives
+MW,-13.254308,34.301525,Malawi
+MX,23.634501,-102.552784,Mexico
+MY,4.210484,101.975766,Malaysia
+MZ,-18.665695,35.529562,Mozambique
+NA,-22.95764,18.49041,Namibia
+NC,-20.904305,165.618042,New Caledonia
+NE,17.607789,8.081666,Niger
+NF,-29.040835,167.954712,Norfolk Island
+NG,9.081999,8.675277,Nigeria
+NI,12.865416,-85.207229,Nicaragua
+NL,52.132633,5.291266,Netherlands
+NO,60.472024,8.468946,Norway
+NP,28.394857,84.124008,Nepal
+NR,-0.522778,166.931503,Nauru
+NU,-19.054445,-169.867233,Niue
+NZ,-40.900557,174.885971,New Zealand
+OM,21.512583,55.923255,Oman
+PA,8.537981,-80.782127,Panama
+PE,-9.189967,-75.015152,Peru
+PF,-17.679742,-149.406843,French Polynesia
+PG,-6.314993,143.95555,Papua New Guinea
+PH,12.879721,121.774017,Philippines
+PK,30.375321,69.345116,Pakistan
+PL,51.919438,19.145136,Poland
+PM,46.941936,-56.27111,Saint Pierre and Miquelon
+PN,-24.703615,-127.439308,Pitcairn Islands
+PR,18.220833,-66.590149,Puerto Rico
+PS,31.952162,35.233154,Palestinian Territories
+PT,39.399872,-8.224454,Portugal
+PW,7.51498,134.58252,Palau
+PY,-23.442503,-58.443832,Paraguay
+QA,25.354826,51.183884,Qatar
+RE,-21.115141,55.536384,R\ufffd\ufffdunion
+RO,45.943161,24.96676,Romania
+RS,44.016521,21.005859,Serbia
+RU,61.52401,105.318756,Russia
+RW,-1.940278,29.873888,Rwanda
+SA,23.885942,45.079162,Saudi Arabia
+SB,-9.64571,160.156194,Solomon Islands
+SC,-4.679574,55.491977,Seychelles
+SD,12.862807,30.217636,Sudan
+SE,60.128161,18.643501,Sweden
+SG,1.352083,103.819836,Singapore
+SH,-24.143474,-10.030696,Saint Helena
+SI,46.151241,14.995463,Slovenia
+SJ,77.553604,23.670272,Svalbard and Jan Mayen
+SK,48.669026,19.699024,Slovakia
+SL,8.460555,-11.779889,Sierra Leone
+SM,43.94236,12.457777,San Marino
+SN,14.497401,-14.452362,Senegal
+SO,5.152149,46.199616,Somalia
+SR,3.919305,-56.027783,Suriname
+ST,0.18636,6.613081,S?o Tom\ufffd\ufffd and Pr\ufffd\ufffdncipe
+SV,13.794185,-88.89653,El Salvador
+SY,34.802075,38.996815,Syria
+SZ,-26.522503,31.465866,Swaziland
+TC,21.694025,-71.797928,Turks and Caicos Islands
+TD,15.454166,18.732207,Chad
+TF,-49.280366,69.348557,French Southern Territories
+TG,8.619543,0.824782,Togo
+TH,15.870032,100.992541,Thailand
+TJ,38.861034,71.276093,Tajikistan
+TK,-8.967363,-171.855881,Tokelau
+TL,-8.874217,125.727539,Timor-Leste
+TM,38.969719,59.556278,Turkmenistan
+TN,33.886917,9.537499,Tunisia
+TO,-21.178986,-175.198242,Tonga
+TR,38.963745,35.243322,Turkey
+TT,10.691803,-61.222503,Trinidad and Tobago
+TV,-7.109535,177.64933,Tuvalu
+TW,23.69781,120.960515,Taiwan
+TZ,-6.369028,34.888822,Tanzania
+UA,48.379433,31.16558,Ukraine
+UG,1.373333,32.290275,Uganda
+US,37.09024,-95.712891,United States
+UY,-32.522779,-55.765835,Uruguay
+UZ,41.377491,64.585262,Uzbekistan
+VA,41.902916,12.453389,Vatican City
+VC,12.984305,-61.287228,Saint Vincent and the Grenadines
+VE,6.42375,-66.58973,Venezuela
+VG,18.420695,-64.639968,British Virgin Islands
+VI,18.335765,-64.896335,U.S. Virgin Islands
+VN,14.058324,108.277199,Vietnam
+VU,-15.376706,166.959158,Vanuatu
+WF,-13.768752,-177.156097,Wallis and Futuna
+WS,-13.759029,-172.104629,Samoa
+XK,42.602636,20.902977,Kosovo
+YE,15.552727,48.516388,Yemen
+YT,-12.8275,45.166244,Mayotte
+ZA,-30.559482,22.937506,South Africa
+ZM,-13.133897,27.849332,Zambia
+ZW,-19.015438,29.154857,Zimbabwe