You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ni...@apache.org on 2019/08/15 13:34:29 UTC

[kylin] 05/11: KYLIN-3628 Fix unexpected exception for select from Lookup Table

This is an automated email from the ASF dual-hosted git repository.

nic pushed a commit to branch 2.6.x
in repository https://gitbox.apache.org/repos/asf/kylin.git

commit 6703c7c5ec2eabc5a6f5f264f44082be332ff881
Author: XiaoxiangYu <hi...@126.com>
AuthorDate: Wed Jul 3 10:18:25 2019 +0800

    KYLIN-3628 Fix unexpected exception for select from Lookup Table
    
    In some case, cube returned by findLatestSnapshot didn't contains the snapshot table
    for what you need. Because some dimension which exists in model but was removed in cube design phase, query such as "select * from LookupTable" will throw unexpected exception and confused user.
---
 .../java/org/apache/kylin/cube/CubeManager.java    | 38 +++++++++++++++++++---
 .../query/enumerator/LookupTableEnumerator.java    |  2 +-
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
index db9c095..6a96f18 100755
--- a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java
@@ -45,6 +45,7 @@ import org.apache.kylin.common.util.Pair;
 import org.apache.kylin.common.util.RandomUtil;
 import org.apache.kylin.cube.cuboid.Cuboid;
 import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.DimensionDesc;
 import org.apache.kylin.cube.model.SnapshotTableDesc;
 import org.apache.kylin.dict.DictionaryInfo;
 import org.apache.kylin.dict.DictionaryManager;
@@ -1223,16 +1224,21 @@ public class CubeManager implements IRealizationProvider {
         }
     }
 
-    public CubeInstance findLatestSnapshot(List<RealizationEntry> realizationEntries, String lookupTableName) {
+    /**
+     * To keep "select * from LOOKUP_TABLE" has consistent and latest result, we manually choose
+     * CubeInstance here to answer such query.
+     */
+    public CubeInstance findLatestSnapshot(List<RealizationEntry> realizationEntries, String lookupTableName,
+            CubeInstance cubeInstance) {
         CubeInstance cube = null;
-        if (realizationEntries.size() > 0) {
+        if (!realizationEntries.isEmpty()) {
             long maxBuildTime = Long.MIN_VALUE;
             RealizationRegistry registry = RealizationRegistry.getInstance(config);
             for (RealizationEntry entry : realizationEntries) {
                 IRealization realization = registry.getRealization(entry.getType(), entry.getRealization());
                 if (realization != null && realization.isReady() && realization instanceof CubeInstance) {
-                    if (realization.getModel().isLookupTable(lookupTableName)) {
-                        CubeInstance current = (CubeInstance) realization;
+                    CubeInstance current = (CubeInstance) realization;
+                    if (checkMeetSnapshotTable(current, lookupTableName)) {
                         CubeSegment segment = current.getLatestReadySegment();
                         if (segment != null) {
                             long latestBuildTime = segment.getLastBuildTime();
@@ -1245,6 +1251,30 @@ public class CubeManager implements IRealizationProvider {
                 }
             }
         }
+        if (!cubeInstance.equals(cube)) {
+            logger.debug("Picked cube {} over {} as it provides a more recent snapshot of the lookup table {}", cube,
+                    cubeInstance, lookupTableName);
+        }
         return cube;
     }
+
+    /**
+     * check if {toCheck} has snapshot of {lookupTableName}
+     * @param lookupTableName look like {SCHMEA}.{TABLE}
+     */
+    private boolean checkMeetSnapshotTable(CubeInstance toCheck, String lookupTableName) {
+        boolean checkRes = false;
+        String lookupTbl = lookupTableName;
+        String[] strArr = lookupTableName.split("\\.");
+        if (strArr.length > 1) {
+            lookupTbl = strArr[strArr.length - 1];
+        }
+        for (DimensionDesc dimensionDesc : toCheck.getDescriptor().getDimensions()) {
+            if (dimensionDesc.getTable().equalsIgnoreCase(lookupTbl)) {
+                checkRes = true;
+                break;
+            }
+        }
+        return checkRes;
+    }
 }
diff --git a/query/src/main/java/org/apache/kylin/query/enumerator/LookupTableEnumerator.java b/query/src/main/java/org/apache/kylin/query/enumerator/LookupTableEnumerator.java
index f8c7ad4..a4f28a8 100644
--- a/query/src/main/java/org/apache/kylin/query/enumerator/LookupTableEnumerator.java
+++ b/query/src/main/java/org/apache/kylin/query/enumerator/LookupTableEnumerator.java
@@ -60,7 +60,7 @@ public class LookupTableEnumerator implements Enumerator<Object[]> {
             List<RealizationEntry> realizationEntries = project.getRealizationEntries();
             String lookupTableName = olapContext.firstTableScan.getTableName();
             CubeManager cubeMgr = CubeManager.getInstance(cube.getConfig());
-            cube = cubeMgr.findLatestSnapshot(realizationEntries, lookupTableName);
+            cube = cubeMgr.findLatestSnapshot(realizationEntries, lookupTableName, cube);
             olapContext.realization = cube;
         } else if (olapContext.realization instanceof HybridInstance) {
             final HybridInstance hybridInstance = (HybridInstance) olapContext.realization;