From 48db473328f1c2218e554dbcebfb98489490f28a Mon Sep 17 00:00:00 2001 From: lidongsjtu Date: Sun, 18 Oct 2015 16:44:43 +0800 Subject: [PATCH] KYLIN-1075 select [MeasureCol] from [FactTbl] is not supported --- .../kylin/metadata/project/ProjectL2Cache.java | 2 +- .../kylin/query/enumerator/CubeEnumerator.java | 61 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java index 2277f40..ead0329 100644 --- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java +++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectL2Cache.java @@ -223,7 +223,7 @@ class ProjectL2Cache { // auto-define table required by realization for some legacy test case if (prjCache.tables.get(table.getIdentity()) == null) { prjCache.tables.put(table.getIdentity(), new TableCache(table)); - logger.warn("Realization '" + realization.getCanonicalName() + "' reports columcn '" + col.getCanonicalName() + "' whose table is not defined in project '" + prjCache.project + "'"); + logger.warn("Realization '" + realization.getCanonicalName() + "' reports column '" + col.getCanonicalName() + "' whose table is not defined in project '" + prjCache.project + "'"); } } diff --git a/query/src/main/java/org/apache/kylin/query/enumerator/CubeEnumerator.java b/query/src/main/java/org/apache/kylin/query/enumerator/CubeEnumerator.java index 64a55a0..3c5c99f 100644 --- a/query/src/main/java/org/apache/kylin/query/enumerator/CubeEnumerator.java +++ b/query/src/main/java/org/apache/kylin/query/enumerator/CubeEnumerator.java @@ -28,6 +28,11 @@ import org.apache.calcite.linq4j.Enumerator; import org.apache.calcite.rel.type.RelDataTypeField; import org.apache.kylin.metadata.filter.CompareTupleFilter; import org.apache.kylin.metadata.filter.TupleFilter; +import org.apache.kylin.metadata.model.FunctionDesc; +import org.apache.kylin.metadata.model.MeasureDesc; +import org.apache.kylin.metadata.model.ParameterDesc; +import org.apache.kylin.metadata.model.TblColRef; +import org.apache.kylin.metadata.realization.SQLDigest; import org.apache.kylin.metadata.tuple.ITuple; import org.apache.kylin.metadata.tuple.ITupleIterator; import org.apache.kylin.query.relnode.OLAPContext; @@ -134,6 +139,9 @@ public class CubeEnumerator implements Enumerator { // bind dynamic variables bindVariable(olapContext.filter); + // hack simple select query for better result + hackNoGroupByAggregation(); + // query storage engine IStorageEngine storageEngine = StorageEngineFactory.getStorageEngine(olapContext.realization); ITupleIterator iterator = storageEngine.search(olapContext.storageContext, olapContext.getSQLDigest()); @@ -176,4 +184,57 @@ public class CubeEnumerator implements Enumerator { int threshold = Integer.valueOf(propThreshold); olapContext.storageContext.setThreshold(threshold); } + + // Hack for better results + private void hackNoGroupByAggregation() { + SQLDigest sqlDigest = olapContext.getSQLDigest(); + + // If no group by and metric found, then it's simple query like select ... from ... where ..., + // But we have no raw data stored, in order to return better results, we hack to output sum of metric data, + if (sqlDigest.groupbyColumns.isEmpty() && sqlDigest.metricColumns.isEmpty()) { + logger.warn("No group by and aggregation found in this query, will hack some result for better look of output..."); + + // If it's select * from ..., + // We need to retrieve cube to manually add columns into sqlDigest, + // So that we have full-columns results as output. + boolean isSelectAll = sqlDigest.allColumns.isEmpty() || sqlDigest.allColumns.equals(sqlDigest.filterColumns); + for (TblColRef cubeColRef : olapContext.realization.getAllColumns()) { + if (cubeColRef.getTable().equals(sqlDigest.factTable) && (olapContext.realization.getAllDimensions().contains(cubeColRef) || isSelectAll)) { + sqlDigest.allColumns.add(cubeColRef); + } + } + + for (TblColRef colRef : sqlDigest.allColumns) { + // For dimension columns, take them as group by columns. + if (olapContext.realization.getAllDimensions().contains(colRef)) { + sqlDigest.groupbyColumns.add(colRef); + } + // For measure columns, take them as metric columns with aggregation function SUM(). + else { + ParameterDesc colParameter = new ParameterDesc(); + colParameter.setType("column"); + colParameter.setValue(colRef.getName()); + FunctionDesc sumFunc = new FunctionDesc(); + sumFunc.setExpression("SUM"); + sumFunc.setParameter(colParameter); + + boolean measureHasSum = false; + for (MeasureDesc colMeasureDesc : olapContext.realization.getMeasures()) { + if (colMeasureDesc.getFunction().equals(sumFunc)) { + measureHasSum = true; + break; + } + } + if (measureHasSum) { + sqlDigest.aggregations.add(sumFunc); + } + else { + logger.warn("SUM is not defined for measure column " + colRef + ", output will be meaningless."); + } + + sqlDigest.metricColumns.add(colRef); + } + } + } + } } -- 2.3.8 (Apple Git-58)