You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lens.apache.org by pr...@apache.org on 2016/10/10 09:41:51 UTC
[2/4] lens git commit: LENS-1273 : Resolve issues with case when
aggregate expressions with dim-attributes conditions
LENS-1273 : Resolve issues with case when aggregate expressions with dim-attributes conditions
Project: http://git-wip-us.apache.org/repos/asf/lens/repo
Commit: http://git-wip-us.apache.org/repos/asf/lens/commit/2cfb7b09
Tree: http://git-wip-us.apache.org/repos/asf/lens/tree/2cfb7b09
Diff: http://git-wip-us.apache.org/repos/asf/lens/diff/2cfb7b09
Branch: refs/heads/master
Commit: 2cfb7b097c5367f21779f3c27bc347a9ff536de1
Parents: 9ef7ce7
Author: Amareshwari Sriramadasu <am...@gmail.com>
Authored: Mon Oct 10 15:09:13 2016 +0530
Committer: Rajat Khandelwal <ra...@gmail.com>
Committed: Mon Oct 10 15:09:13 2016 +0530
----------------------------------------------------------------------
.../lens/cube/parse/AggregateResolver.java | 24 ---
.../apache/lens/cube/parse/AliasReplacer.java | 75 ++++----
.../apache/lens/cube/parse/CandidateFact.java | 2 +-
.../lens/cube/parse/CandidateTableResolver.java | 161 +++++++++-------
.../apache/lens/cube/parse/ColumnResolver.java | 110 +++++++----
.../lens/cube/parse/CubeQueryContext.java | 123 ++++--------
.../cube/parse/DenormalizationResolver.java | 4 +-
.../lens/cube/parse/ExpressionResolver.java | 16 +-
.../apache/lens/cube/parse/GroupbyResolver.java | 111 +++--------
.../lens/cube/parse/MultiFactHQLContext.java | 9 +-
.../lens/cube/parse/QueriedPhraseContext.java | 186 +++++++++++++++++++
.../lens/cube/parse/SelectPhraseContext.java | 51 +++++
.../lens/cube/parse/TimeRangeChecker.java | 4 +-
.../lens/cube/parse/TrackQueriedColumns.java | 29 ++-
.../lens/cube/parse/TrackQueriedCubeFields.java | 66 +++++++
.../lens/cube/parse/TracksQueriedColumns.java | 59 ++++++
.../apache/lens/cube/parse/CubeTestSetup.java | 3 +
.../lens/cube/parse/TestAggregateResolver.java | 62 +++----
.../lens/cube/parse/TestBaseCubeQueries.java | 115 +++++++++++-
19 files changed, 821 insertions(+), 389 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/AggregateResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/AggregateResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/AggregateResolver.java
index 292868a..c522061 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/AggregateResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/AggregateResolver.java
@@ -159,15 +159,6 @@ class AggregateResolver implements ContextRewriter {
if (wrapped != node) {
if (parent != null) {
parent.setChild(nodePos, wrapped);
- // Check if this node has an alias
- ASTNode sibling = HQLParser.findNodeByPath(parent, Identifier);
- String expr;
- if (sibling != null) {
- expr = HQLParser.getString(parent);
- } else {
- expr = HQLParser.getString(wrapped);
- }
- cubeql.addAggregateExpr(expr.trim());
} else {
return wrapped;
}
@@ -342,19 +333,4 @@ class AggregateResolver implements ContextRewriter {
return false;
}
-
- static void updateAggregates(ASTNode root, CubeQueryContext cubeql) {
- if (root == null) {
- return;
- }
-
- if (HQLParser.isAggregateAST(root)) {
- cubeql.addAggregateExpr(HQLParser.getString(root).trim());
- } else {
- for (int i = 0; i < root.getChildCount(); i++) {
- ASTNode child = (ASTNode) root.getChild(i);
- updateAggregates(child, cubeql);
- }
- }
- }
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/AliasReplacer.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/AliasReplacer.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/AliasReplacer.java
index 5b48ca4..da34242 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/AliasReplacer.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/AliasReplacer.java
@@ -18,10 +18,6 @@
*/
package org.apache.lens.cube.parse;
-import static org.apache.hadoop.hive.ql.parse.HiveParser.Identifier;
-import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_SELEXPR;
-
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -54,7 +50,11 @@ class AliasReplacer implements ContextRewriter {
Map<String, String> colToTableAlias = cubeql.getColToTableAlias();
extractTabAliasForCol(cubeql);
- findDimAttributesAndMeasures(cubeql);
+ // Resolve aliases in all queried phrases
+ for (QueriedPhraseContext qur : cubeql.getQueriedPhrases()) {
+ extractTabAliasForCol(colToTableAlias, qur);
+ }
+ findExpressionsAndMeasures(cubeql);
if (colToTableAlias.isEmpty()) {
return;
@@ -83,11 +83,6 @@ class AliasReplacer implements ContextRewriter {
replaceAliases(cubeql.getJoinAST(), 0, colToTableAlias);
- // Update the aggregate expression set
- AggregateResolver.updateAggregates(cubeql.getSelectAST(), cubeql);
- AggregateResolver.updateAggregates(cubeql.getHavingAST(), cubeql);
- // Update alias map as well
- updateAliasMap(cubeql.getSelectAST(), cubeql);
}
/**
@@ -95,27 +90,26 @@ class AliasReplacer implements ContextRewriter {
* @param cubeql
* @throws LensException
*/
- private void findDimAttributesAndMeasures(CubeQueryContext cubeql) throws LensException {
+ private void findExpressionsAndMeasures(CubeQueryContext cubeql) throws LensException {
CubeInterface cube = cubeql.getCube();
if (cube != null) {
- Set<String> cubeColsQueried = cubeql.getColumnsQueried(cube.getName());
- Set<String> queriedDimAttrs = new HashSet<String>();
- Set<String> queriedMsrs = new HashSet<String>();
- Set<String> queriedExprs = new HashSet<String>();
- if (cubeColsQueried != null && !cubeColsQueried.isEmpty()) {
- for (String col : cubeColsQueried) {
- if (cube.getMeasureNames().contains(col)) {
- queriedMsrs.add(col);
- } else if (cube.getDimAttributeNames().contains(col)) {
- queriedDimAttrs.add(col);
- } else if (cube.getExpressionNames().contains(col)) {
- queriedExprs.add(col);
+ String cubeAlias = cubeql.getAliasForTableName(cube.getName());
+ for (QueriedPhraseContext qur : cubeql.getQueriedPhrases()) {
+ Set<String> cubeColsQueried = qur.getColumnsQueried(cubeAlias);
+ if (cubeColsQueried != null && !cubeColsQueried.isEmpty()) {
+ for (String col : cubeColsQueried) {
+ if (cube.getMeasureNames().contains(col)) {
+ qur.addQueriedMsr(col);
+ } else if (cube.getDimAttributeNames().contains(col)) {
+ qur.addQueriedDimAttr(col);
+ } else if (cube.getExpressionNames().contains(col)) {
+ qur.addQueriedExprColumn(col);
+ }
}
}
+ cubeql.addQueriedMsrs(qur.getQueriedMsrs());
+ cubeql.addQueriedExprs(qur.getQueriedExprColumns());
}
- cubeql.addQueriedDimAttrs(queriedDimAttrs);
- cubeql.addQueriedMsrs(queriedMsrs);
- cubeql.addQueriedExprs(queriedExprs);
}
}
@@ -164,6 +158,18 @@ class AliasReplacer implements ContextRewriter {
}
}
+ static void extractTabAliasForCol(Map<String, String> colToTableAlias, TrackQueriedColumns tqc) throws LensException {
+ Set<String> columns = tqc.getTblAliasToColumns().get(CubeQueryContext.DEFAULT_TABLE);
+ if (columns == null) {
+ return;
+ }
+ for (String col : columns) {
+ tqc.addColumnsQueried(colToTableAlias.get(col.toLowerCase()), col.toLowerCase());
+ if (colToTableAlias.get(col.toLowerCase()) == null) {
+ throw new LensException(LensCubeErrorCode.COLUMN_NOT_FOUND.getLensErrorInfo(), col);
+ }
+ }
+ }
static ASTNode replaceAliases(ASTNode node, int nodePos, Map<String, String> colToTableAlias) {
if (node == null) {
return node;
@@ -213,21 +219,4 @@ class AliasReplacer implements ContextRewriter {
return node;
}
- static void updateAliasMap(ASTNode root, CubeQueryContext cubeql) {
- if (root == null) {
- return;
- }
-
- if (root.getToken().getType() == TOK_SELEXPR) {
- ASTNode alias = HQLParser.findNodeByPath(root, Identifier);
- if (alias != null) {
- cubeql.addExprToAlias(root, alias);
- }
- } else {
- for (int i = 0; i < root.getChildCount(); i++) {
- updateAliasMap((ASTNode) root.getChild(i), cubeql);
- }
- }
- }
-
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateFact.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateFact.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateFact.java
index 01265a5..5dc9dc9 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateFact.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateFact.java
@@ -193,7 +193,7 @@ public class CandidateFact implements CandidateTable, QueryAST {
dimFieldIndices.add(i);
}
ASTNode aliasNode = HQLParser.findNodeByPath(selectExpr, Identifier);
- String alias = cubeql.getSelectAlias(i);
+ String alias = cubeql.getSelectPhrases().get(i).getSelectAlias();
if (aliasNode != null) {
String queryAlias = aliasNode.getText();
if (!queryAlias.equals(alias)) {
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateTableResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateTableResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateTableResolver.java
index 83e5088..510bd8c 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateTableResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/CandidateTableResolver.java
@@ -52,7 +52,7 @@ class CandidateTableResolver implements ContextRewriter {
private boolean checkForQueriedColumns = true;
- public CandidateTableResolver(Configuration conf) {
+ public CandidateTableResolver(Configuration ignored) {
}
@Override
@@ -233,10 +233,17 @@ class CandidateTableResolver implements ContextRewriter {
String str = cubeql.getConf().get(CubeQueryConfUtil.getValidFactTablesKey(cubeql.getCube().getName()));
List<String> validFactTables =
StringUtils.isBlank(str) ? null : Arrays.asList(StringUtils.split(str.toLowerCase(), ","));
- Set<String> queriedDimAttrs = cubeql.getQueriedDimAttrs();
- Set<String> queriedMsrs = cubeql.getQueriedMsrs();
- // Remove fact tables based on columns in the query
+ Set<QueriedPhraseContext> queriedMsrs = new HashSet<>();
+ Set<QueriedPhraseContext> dimExprs = new HashSet<>();
+ for (QueriedPhraseContext qur : cubeql.getQueriedPhrases()) {
+ if (qur.hasMeasures(cubeql)) {
+ queriedMsrs.add(qur);
+ } else {
+ dimExprs.add(qur);
+ }
+ }
+ // Remove fact tables based on whether they are valid or not.
for (Iterator<CandidateFact> i = cubeql.getCandidateFacts().iterator(); i.hasNext();) {
CandidateFact cfact = i.next();
@@ -249,26 +256,37 @@ class CandidateTableResolver implements ContextRewriter {
continue;
}
}
+
+ // update expression evaluability for this fact
+ for (String expr : cubeql.getQueriedExprs()) {
+ cubeql.getExprCtx().updateEvaluables(expr, cfact);
+ }
+
// go over the columns accessed in the query and find out which tables
// can answer the query
// the candidate facts should have all the dimensions queried and
// atleast
// one measure
boolean toRemove = false;
- for (String col : queriedDimAttrs) {
- if (!cfact.getColumns().contains(col.toLowerCase())) {
- // check if it available as reference, if not remove the candidate
- if (!cubeql.getDeNormCtx().addRefUsage(cfact, col, cubeql.getCube().getName())) {
- log.info("Not considering fact table:{} as column {} is not available", cfact, col);
- cubeql.addFactPruningMsgs(cfact.fact, CandidateTablePruneCause.columnNotFound(col));
- toRemove = true;
- break;
- }
- } else if (!isFactColumnValidForRange(cubeql, cfact, col)) {
+ for (QueriedPhraseContext qur : dimExprs) {
+ if (!qur.isEvaluable(cubeql, cfact)) {
+ log.info("Not considering fact table:{} as columns {} are not available", cfact, qur.getColumns());
+ cubeql.addFactPruningMsgs(cfact.fact, CandidateTablePruneCause.columnNotFound(qur.getColumns()));
toRemove = true;
break;
}
}
+
+ // check if the candidate fact has atleast one measure queried
+ // if expression has measures, they should be considered along with other measures and see if the fact can be
+ // part of measure covering set
+ if (!checkForFactColumnExistsAndValidForRange(cfact, queriedMsrs, cubeql)) {
+ Set<String> columns = getColumns(queriedMsrs);
+
+ log.info("Not considering fact table:{} as columns {} is not available", cfact, columns);
+ cubeql.addFactPruningMsgs(cfact.fact, CandidateTablePruneCause.columnNotFound(columns));
+ toRemove = true;
+ }
// go over join chains and prune facts that dont have any of the columns in each chain
for (JoinChain chain : cubeql.getJoinchains().values()) {
OptionalDimCtx optdim = cubeql.getOptionalDimensionMap().get(Aliased.create((Dimension)cubeql.getCubeTbls()
@@ -284,45 +302,17 @@ class CandidateTableResolver implements ContextRewriter {
}
}
}
- // go over expressions queried
- // if expression has no measures, prune facts which cannot evaluate expression
- // if expression has measures, they should be considered along with other measures and see if the fact can be
- // part of measure covering set
- for (String expr : cubeql.getQueriedExprs()) {
- cubeql.getExprCtx().updateEvaluables(expr, cfact);
- if (!cubeql.getQueriedExprsWithMeasures().contains(expr) && !cubeql.getExprCtx().isEvaluable(expr, cfact)) {
- // if expression has no measures, prune facts which cannot evaluate expression
- log.info("Not considering fact table:{} as expression {} is not evaluatable", cfact, expr);
- cubeql.addFactPruningMsgs(cfact.fact, CandidateTablePruneCause.expressionNotEvaluable(expr));
- toRemove = true;
- break;
- }
- }
- // check if the candidate fact has atleast one measure queried
- // if expression has measures, they should be considered along with other measures and see if the fact can be
- // part of measure covering set
- if (!checkForFactColumnExistsAndValidForRange(cfact, queriedMsrs, cubeql)
- && (cubeql.getQueriedExprsWithMeasures().isEmpty()
- || cubeql.getExprCtx().allNotEvaluable(cubeql.getQueriedExprsWithMeasures(), cfact))) {
- log.info("Not considering fact table:{} as columns {},{} is not available", cfact, queriedMsrs,
- cubeql.getQueriedExprsWithMeasures());
- cubeql.addFactPruningMsgs(cfact.fact, CandidateTablePruneCause.columnNotFound(queriedMsrs,
- cubeql.getQueriedExprsWithMeasures()));
- toRemove = true;
- }
+
if (toRemove) {
i.remove();
}
}
- Set<String> dimExprs = new HashSet<>(cubeql.getQueriedExprs());
- dimExprs.removeAll(cubeql.getQueriedExprsWithMeasures());
if (cubeql.getCandidateFacts().size() == 0) {
throw new LensException(LensCubeErrorCode.NO_FACT_HAS_COLUMN.getLensErrorInfo(),
- (!queriedDimAttrs.isEmpty() ? queriedDimAttrs.toString() : "")
- + (!dimExprs.isEmpty() ? dimExprs.toString() : ""));
+ getColumns(cubeql.getQueriedPhrases()).toString());
}
Set<Set<CandidateFact>> cfactset;
- if (queriedMsrs.isEmpty() && cubeql.getQueriedExprsWithMeasures().isEmpty()) {
+ if (queriedMsrs.isEmpty()) {
// if no measures are queried, add all facts individually as single covering sets
cfactset = new HashSet<>();
for (CandidateFact cfact : cubeql.getCandidateFacts()) {
@@ -334,18 +324,16 @@ class CandidateTableResolver implements ContextRewriter {
} else {
// Find out candidate fact table sets which contain all the measures
// queried
+
List<CandidateFact> cfacts = new ArrayList<>(cubeql.getCandidateFacts());
- cfactset = findCoveringSets(cubeql, cfacts, queriedMsrs,
- cubeql.getQueriedExprsWithMeasures());
+ cfactset = findCoveringSets(cubeql, cfacts, queriedMsrs);
log.info("Measure covering fact sets :{}", cfactset);
- String msrString = (!queriedMsrs.isEmpty() ? queriedMsrs.toString() : "")
- + (!cubeql.getQueriedExprsWithMeasures().isEmpty() ? cubeql.getQueriedExprsWithMeasures().toString() : "");
+ String msrString = getColumns(queriedMsrs).toString();
if (cfactset.isEmpty()) {
throw new LensException(LensCubeErrorCode.NO_FACT_HAS_COLUMN.getLensErrorInfo(), msrString);
}
cubeql.getCandidateFactSets().addAll(cfactset);
- cubeql.pruneCandidateFactWithCandidateSet(CandidateTablePruneCause.columnNotFound(queriedMsrs,
- cubeql.getQueriedExprsWithMeasures()));
+ cubeql.pruneCandidateFactWithCandidateSet(CandidateTablePruneCause.columnNotFound(getColumns(queriedMsrs)));
if (cubeql.getCandidateFacts().size() == 0) {
throw new LensException(LensCubeErrorCode.NO_FACT_HAS_COLUMN.getLensErrorInfo(), msrString);
@@ -354,19 +342,25 @@ class CandidateTableResolver implements ContextRewriter {
}
}
+ private static Set<String> getColumns(Collection<QueriedPhraseContext> queriedPhraseContexts) {
+ Set<String> cols = new HashSet<>();
+ for (QueriedPhraseContext qur : queriedPhraseContexts) {
+ cols.addAll(qur.getColumns());
+ }
+ return cols;
+ }
static Set<Set<CandidateFact>> findCoveringSets(CubeQueryContext cubeql, List<CandidateFact> cfactsPassed,
- Set<String> msrs, Set<String> exprsWithMeasures) {
+ Set<QueriedPhraseContext> msrs) throws LensException {
Set<Set<CandidateFact>> cfactset = new HashSet<>();
List<CandidateFact> cfacts = new ArrayList<>(cfactsPassed);
for (Iterator<CandidateFact> i = cfacts.iterator(); i.hasNext();) {
CandidateFact cfact = i.next();
i.remove();
- // cfact does not contain any of msrs and none of exprsWithMeasures are evaluable.
- if ((msrs.isEmpty() || !checkForFactColumnExistsAndValidForRange(cfact, msrs, cubeql))
- && (exprsWithMeasures.isEmpty() || cubeql.getExprCtx().allNotEvaluable(exprsWithMeasures, cfact))) {
+ if (!checkForFactColumnExistsAndValidForRange(cfact, msrs, cubeql)) {
+ // cfact does not contain any of msrs and none of exprsWithMeasures are evaluable.
// ignore the fact
continue;
- } else if (cfact.getColumns().containsAll(msrs) && cubeql.getExprCtx().allEvaluable(cfact, exprsWithMeasures)) {
+ } else if (allEvaluable(cfact, msrs, cubeql)) {
// return single set
Set<CandidateFact> one = new LinkedHashSet<>();
one.add(cfact);
@@ -374,18 +368,18 @@ class CandidateTableResolver implements ContextRewriter {
} else {
// find the remaining measures in other facts
if (i.hasNext()) {
- Set<String> remainingMsrs = new HashSet<>(msrs);
- Set<String> remainingExprs = new HashSet<>(exprsWithMeasures);
- remainingMsrs.removeAll(cfact.getColumns());
- remainingExprs.removeAll(cubeql.getExprCtx().coveringExpressions(exprsWithMeasures, cfact));
- Set<Set<CandidateFact>> coveringSets = findCoveringSets(cubeql, cfacts, remainingMsrs, remainingExprs);
+ Set<QueriedPhraseContext> remainingMsrs = new HashSet<>(msrs);
+ Set<QueriedPhraseContext> coveredMsrs = coveredMeasures(cfact, msrs, cubeql);
+ remainingMsrs.removeAll(coveredMsrs);
+
+ Set<Set<CandidateFact>> coveringSets = findCoveringSets(cubeql, cfacts, remainingMsrs);
if (!coveringSets.isEmpty()) {
for (Set<CandidateFact> set : coveringSets) {
set.add(cfact);
cfactset.add(set);
}
} else {
- log.info("Couldnt find any set containing remaining measures:{} {} in {}", remainingMsrs, remainingExprs,
+ log.info("Couldnt find any set containing remaining measures:{} {} in {}", remainingMsrs,
cfactsPassed);
}
}
@@ -682,8 +676,8 @@ class CandidateTableResolver implements ContextRewriter {
// can answer the query
for (Iterator<CandidateDim> i = cubeql.getCandidateDimTables().get(dim).iterator(); i.hasNext();) {
CandidateDim cdim = i.next();
- if (cubeql.getColumnsQueried(dim.getName()) != null) {
- for (String col : cubeql.getColumnsQueried(dim.getName())) {
+ if (cubeql.getColumnsQueriedForTable(dim.getName()) != null) {
+ for (String col : cubeql.getColumnsQueriedForTable(dim.getName())) {
if (!cdim.getColumns().contains(col.toLowerCase())) {
// check if the column is an expression
if (cdim.getBaseTable().getExpressionNames().contains(col)) {
@@ -711,7 +705,7 @@ class CandidateTableResolver implements ContextRewriter {
if (cubeql.getCandidateDimTables().get(dim).size() == 0) {
throw new LensException(LensCubeErrorCode.NO_DIM_HAS_COLUMN.getLensErrorInfo(), dim.getName(), cubeql
- .getColumnsQueried(dim.getName()).toString());
+ .getColumnsQueriedForTable(dim.getName()).toString());
}
}
}
@@ -731,4 +725,41 @@ class CandidateTableResolver implements ContextRewriter {
}
return false;
}
+
+ static boolean checkForFactColumnExistsAndValidForRange(CandidateFact table, Collection<QueriedPhraseContext> colSet,
+ CubeQueryContext cubeql) throws LensException {
+ if (colSet == null || colSet.isEmpty()) {
+ return true;
+ }
+ for (QueriedPhraseContext qur : colSet) {
+ if (qur.isEvaluable(cubeql, table)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static boolean allEvaluable(CandidateFact table, Collection<QueriedPhraseContext> colSet,
+ CubeQueryContext cubeql) throws LensException {
+ if (colSet == null || colSet.isEmpty()) {
+ return true;
+ }
+ for (QueriedPhraseContext qur : colSet) {
+ if (!qur.isEvaluable(cubeql, table)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static Set<QueriedPhraseContext> coveredMeasures(CandidateFact table, Collection<QueriedPhraseContext> msrs,
+ CubeQueryContext cubeql) throws LensException {
+ Set<QueriedPhraseContext> coveringSet = new HashSet<>();
+ for (QueriedPhraseContext msr : msrs) {
+ if (msr.isEvaluable(cubeql, table)) {
+ coveringSet.add(msr);
+ }
+ }
+ return coveringSet;
+ }
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/ColumnResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/ColumnResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/ColumnResolver.java
index 2db5dd1..87e094a 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/ColumnResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/ColumnResolver.java
@@ -28,8 +28,11 @@ import org.apache.lens.cube.parse.HQLParser.ASTNodeVisitor;
import org.apache.lens.cube.parse.HQLParser.TreeNode;
import org.apache.lens.server.api.error.LensException;
+import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.ql.lib.Node;
import org.apache.hadoop.hive.ql.parse.ASTNode;
+import org.apache.hadoop.hive.ql.parse.HiveParser;
import com.google.common.base.Optional;
@@ -40,10 +43,11 @@ class ColumnResolver implements ContextRewriter {
@Override
public void rewriteContext(CubeQueryContext cubeql) throws LensException {
+ checkForAllColumnsSelected(cubeql);
extractColumns(cubeql);
}
- private void extractColumns(CubeQueryContext cubeql) throws LensException {
+ private void checkForAllColumnsSelected(CubeQueryContext cubeql) throws LensException {
// Check if its 'select * from...'
ASTNode selTree = cubeql.getSelectAST();
if (selTree.getChildCount() == 1) {
@@ -59,12 +63,15 @@ class ColumnResolver implements ContextRewriter {
}
}
}
+ }
+
+ private void extractColumns(CubeQueryContext cubeql) throws LensException {
getColsForSelectTree(cubeql);
getColsForWhereTree(cubeql);
- getColsForTree(cubeql, cubeql.getJoinAST(), cubeql, true);
- getColsForTree(cubeql, cubeql.getGroupByAST(), cubeql, true);
- getColsForTree(cubeql, cubeql.getHavingAST(), cubeql, true);
- getColsForTree(cubeql, cubeql.getOrderByAST(), cubeql, true);
+ getColsForAST(cubeql, cubeql.getJoinAST());
+ getColsForAST(cubeql, cubeql.getGroupByAST());
+ getColsForHavingAST(cubeql, cubeql.getHavingAST());
+ getColsForAST(cubeql, cubeql.getOrderByAST());
// Update join dimension tables
for (String table : cubeql.getTblAliasToColumns().keySet()) {
@@ -76,6 +83,38 @@ class ColumnResolver implements ContextRewriter {
}
}
+ private void getColsForAST(CubeQueryContext cubeql, ASTNode clause) throws LensException {
+ if (clause == null) {
+ return;
+ }
+ for (int i = 0; i < clause.getChildCount(); i++) {
+ ASTNode queriedExpr = (ASTNode) clause.getChild(i);
+ QueriedPhraseContext qur = new QueriedPhraseContext(queriedExpr);
+ getColsForTree(cubeql, queriedExpr, qur, true);
+ cubeql.addColumnsQueried(qur.getTblAliasToColumns());
+ cubeql.addQueriedPhrase(qur);
+ }
+ }
+
+ private void getColsForHavingAST(CubeQueryContext cubeql, ASTNode clause) throws LensException {
+ if (clause == null) {
+ return;
+ }
+
+ // split having clause phrases to be column level sothat having clause can be pushed to multiple facts if required.
+ if (HQLParser.isAggregateAST(clause) || clause.getType() == HiveParser.TOK_TABLE_OR_COL
+ || clause.getType() == HiveParser.DOT || clause.getChildCount() == 0) {
+ QueriedPhraseContext qur = new QueriedPhraseContext(clause);
+ qur.setAggregate(true);
+ getColsForTree(cubeql, clause, qur, true);
+ cubeql.addColumnsQueried(qur.getTblAliasToColumns());
+ cubeql.addQueriedPhrase(qur);
+ } else {
+ for (Node child : clause.getChildren()) {
+ getColsForHavingAST(cubeql, (ASTNode)child);
+ }
+ }
+ }
// finds columns in AST passed.
static void getColsForTree(final CubeQueryContext cubeql, ASTNode tree, final TrackQueriedColumns tqc,
final boolean skipAliases)
@@ -99,7 +138,7 @@ class ColumnResolver implements ContextRewriter {
// Take child ident.totext
ASTNode ident = (ASTNode) node.getChild(0);
String column = ident.getText().toLowerCase();
- if (skipAliases && cubeql.getExprToAliasMap().values().contains(column)) {
+ if (skipAliases && cubeql.isColumnAnAlias(column)) {
// column is an existing alias
return;
}
@@ -129,7 +168,13 @@ class ColumnResolver implements ContextRewriter {
if (cubeql.getWhereAST() == null) {
return;
}
- addColumnsForWhere(cubeql, cubeql.getWhereAST(), null);
+ for (int i = 0; i < cubeql.getWhereAST().getChildCount(); i++) {
+ ASTNode queriedExpr = (ASTNode) cubeql.getWhereAST().getChild(i);
+ QueriedPhraseContext qur = new QueriedPhraseContext(queriedExpr);
+ addColumnsForWhere(cubeql, qur, queriedExpr, cubeql.getWhereAST());
+ cubeql.addColumnsQueried(qur.getTblAliasToColumns());
+ cubeql.addQueriedPhrase(qur);
+ }
}
// Find all columns of select tree.
@@ -153,13 +198,13 @@ class ColumnResolver implements ContextRewriter {
ASTNode selectExpr = (ASTNode) cubeql.getSelectAST().getChild(i);
ASTNode selectExprChild = (ASTNode)selectExpr.getChild(0);
Set<String> cols = new HashSet<>();
- addColumnsForSelectExpr(cubeql, selectExpr, cubeql.getSelectAST(), cols);
- ASTNode alias = HQLParser.findNodeByPath(selectExpr, Identifier);
+ SelectPhraseContext sel = new SelectPhraseContext(selectExpr);
+ addColumnsForSelectExpr(sel, selectExpr, cubeql.getSelectAST(), cols);
+ String alias = selectExpr.getChildCount() > 1 ? selectExpr.getChild(1).getText() : null;
String selectAlias;
String selectFinalAlias = null;
if (alias != null) {
- cubeql.addExprToAlias(selectExpr, alias);
- selectFinalAlias = alias.getText();
+ selectFinalAlias = alias;
selectAlias = SELECT_ALIAS_PREFIX + exprInd;
} else if (cols.size() == 1 && (selectExprChild.getToken().getType() == TOK_TABLE_OR_COL
|| selectExprChild.getToken().getType() == DOT)) {
@@ -170,21 +215,26 @@ class ColumnResolver implements ContextRewriter {
selectFinalAlias = HQLParser.getString(selectExprChild);
}
exprInd++;
- cubeql.addSelectAlias(selectAlias, selectFinalAlias);
+ cubeql.addColumnsQueried(sel.getTblAliasToColumns());
+ sel.setSelectAlias(selectAlias);
+ sel.setFinalAlias(!StringUtils.isBlank(selectFinalAlias) ? "`" + selectFinalAlias + "`" : selectAlias);
+ sel.setActualAlias(alias != null ? alias.toLowerCase() : null);
+ cubeql.addSelectPhrase(sel);
}
}
- private static void addColumnsForWhere(final CubeQueryContext cubeql, ASTNode node, ASTNode parent) {
+ private static void addColumnsForWhere(final CubeQueryContext cubeql, QueriedPhraseContext qur, ASTNode node,
+ ASTNode parent) {
if (node.getToken().getType() == TOK_TABLE_OR_COL && (parent != null && parent.getToken().getType() != DOT)) {
// Take child ident.totext
ASTNode ident = (ASTNode) node.getChild(0);
String column = ident.getText().toLowerCase();
- if (cubeql.getExprToAliasMap().values().contains(column)) {
+ if (cubeql.isColumnAnAlias(column)) {
// column is an existing alias
return;
}
- addColumnQueriedWithTimeRangeFuncCheck(cubeql, parent, CubeQueryContext.DEFAULT_TABLE, column);
+ addColumnQueriedWithTimeRangeFuncCheck(cubeql, qur, parent, CubeQueryContext.DEFAULT_TABLE, column);
} else if (node.getToken().getType() == DOT) {
// This is for the case where column name is prefixed by table name
@@ -197,32 +247,31 @@ class ColumnResolver implements ContextRewriter {
String column = colIdent.getText().toLowerCase();
String table = tabident.getText().toLowerCase();
- addColumnQueriedWithTimeRangeFuncCheck(cubeql, parent, table, column);
+ addColumnQueriedWithTimeRangeFuncCheck(cubeql, qur, parent, table, column);
} else if (node.getToken().getType() == TOK_FUNCTION) {
ASTNode fname = HQLParser.findNodeByPath(node, Identifier);
if (fname != null && CubeQueryContext.TIME_RANGE_FUNC.equalsIgnoreCase(fname.getText())) {
- addColumnsForWhere(cubeql, (ASTNode) node.getChild(1), node);
+ addColumnsForWhere(cubeql, qur, (ASTNode) node.getChild(1), node);
} else {
for (int i = 0; i < node.getChildCount(); i++) {
- addColumnsForWhere(cubeql, (ASTNode) node.getChild(i), node);
+ addColumnsForWhere(cubeql, qur, (ASTNode) node.getChild(i), node);
}
}
} else {
for (int i = 0; i < node.getChildCount(); i++) {
- addColumnsForWhere(cubeql, (ASTNode) node.getChild(i), node);
+ addColumnsForWhere(cubeql, qur, (ASTNode) node.getChild(i), node);
}
}
}
- private static void addColumnQueriedWithTimeRangeFuncCheck(final CubeQueryContext cubeql, final ASTNode parent,
- final String table, final String column) {
-
+ private static void addColumnQueriedWithTimeRangeFuncCheck(final CubeQueryContext cubeql, QueriedPhraseContext qur,
+ final ASTNode parent, final String table, final String column) {
if (isTimeRangeFunc(parent)) {
cubeql.addQueriedTimeDimensionCols(column);
- cubeql.addColumnsQueriedWithTimeDimCheck(CubeQueryContext.DEFAULT_TABLE, column);
+ cubeql.addColumnsQueriedWithTimeDimCheck(qur, CubeQueryContext.DEFAULT_TABLE, column);
} else {
- cubeql.addColumnsQueried(table, column);
+ qur.addColumnsQueried(table, column);
}
}
@@ -244,17 +293,14 @@ class ColumnResolver implements ContextRewriter {
}
return Optional.fromNullable(funcName);
}
- private static void addColumnsForSelectExpr(final CubeQueryContext cubeql, ASTNode node, ASTNode parent,
+
+ private static void addColumnsForSelectExpr(final TrackQueriedColumns sel, ASTNode node, ASTNode parent,
Set<String> cols) {
if (node.getToken().getType() == TOK_TABLE_OR_COL && (parent != null && parent.getToken().getType() != DOT)) {
// Take child ident.totext
ASTNode ident = (ASTNode) node.getChild(0);
String column = ident.getText().toLowerCase();
- if (cubeql.getExprToAliasMap().values().contains(column)) {
- // column is an existing alias
- return;
- }
- cubeql.addColumnsQueried(CubeQueryContext.DEFAULT_TABLE, column);
+ sel.addColumnsQueried(CubeQueryContext.DEFAULT_TABLE, column);
cols.add(column);
} else if (node.getToken().getType() == DOT) {
// This is for the case where column name is prefixed by table name
@@ -266,11 +312,11 @@ class ColumnResolver implements ContextRewriter {
String column = colIdent.getText().toLowerCase();
String table = tabident.getText().toLowerCase();
- cubeql.addColumnsQueried(table, column);
+ sel.addColumnsQueried(table, column);
cols.add(column);
} else {
for (int i = 0; i < node.getChildCount(); i++) {
- addColumnsForSelectExpr(cubeql, (ASTNode) node.getChild(i), node, cols);
+ addColumnsForSelectExpr(sel, (ASTNode) node.getChild(i), node, cols);
}
}
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryContext.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryContext.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryContext.java
index 63ec8b2..6d53d00 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryContext.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryContext.java
@@ -59,7 +59,7 @@ import lombok.*;
import lombok.extern.slf4j.Slf4j;
@Slf4j
-public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
+public class CubeQueryContext extends TracksQueriedColumns implements QueryAST {
public static final String TIME_RANGE_FUNC = "time_range_in";
public static final String NOW = "now";
public static final String DEFAULT_TABLE = "_default_";
@@ -86,7 +86,6 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
// Joinchains accessed in the query
@Getter
protected Map<String, JoinChain> joinchains = new HashMap<String, JoinChain>();
- private final Set<String> queriedDimAttrs = new HashSet<String>();
@Getter
private final Set<String> queriedMsrs = new HashSet<String>();
@@ -112,20 +111,31 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
// Alias to table object mapping of tables accessed in this query
@Getter
- private final Map<String, AbstractCubeTable> cubeTbls = new HashMap<String, AbstractCubeTable>();
- // Alias name to fields queried
- @Getter
- private final Map<String, Set<String>> tblAliasToColumns = new HashMap<String, Set<String>>();
- // Mapping of an expression to its column alias in the query
- @Getter
- private final Map<String, String> exprToAlias = new HashMap<String, String>();
- @Getter
- private final List<String> selectAliases = new ArrayList<String>();
+ private final Map<String, AbstractCubeTable> cubeTbls = new HashMap<>();
+
+ void addSelectPhrase(SelectPhraseContext sel) {
+ selectPhrases.add(sel);
+ addQueriedPhrase(sel);
+ }
+
+ boolean isColumnAnAlias(String col) {
+ for (SelectPhraseContext sel : selectPhrases) {
+ if (col.equals(sel.getActualAlias())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void addQueriedPhrase(QueriedPhraseContext qur) {
+ queriedPhrases.add(qur);
+ }
@Getter
- private final List<String> selectFinalAliases = new ArrayList<String>();
- // All aggregate expressions in the query
+ private final List<SelectPhraseContext> selectPhrases = new ArrayList<>();
+
@Getter
- private final Set<String> aggregateExprs = new HashSet<String>();
+ private final List<QueriedPhraseContext> queriedPhrases = new ArrayList<>();
+
// Join conditions used in all join expressions
@Getter
private final Map<QBJoinTree, String> joinConds = new HashMap<QBJoinTree, String>();
@@ -203,11 +213,6 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
this.selectAST = qb.getParseInfo().getSelForClause(clauseName);
}
- for (ASTNode aggrTree : qb.getParseInfo().getAggregationExprsForClause(clauseName).values()) {
- String aggr = HQLParser.getString(aggrTree);
- aggregateExprs.add(aggr);
- }
-
extractMetaTables();
}
@@ -670,10 +675,6 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
return qb.getParseInfo().getJoinExpr();
}
- public QBJoinTree getQBJoinTree() {
- return qb.getQbJoinTree();
- }
-
public String getOrderByString() {
if (orderByAST != null) {
return HQLParser.getString(orderByAST);
@@ -1037,25 +1038,15 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
return ParseUtils.findRootNonNullToken(tree);
}
- public Set<String> getColumnsQueried(String tblName) {
- return tblAliasToColumns.get(getAliasForTableName(tblName));
+ public Set<String> getColumnsQueriedForTable(String tblName) {
+ return getColumnsQueried(getAliasForTableName(tblName));
}
- public void addColumnsQueriedWithTimeDimCheck(String alias, String timeDimColumn) {
+ public void addColumnsQueriedWithTimeDimCheck(QueriedPhraseContext qur, String alias, String timeDimColumn) {
if (!shouldReplaceTimeDimWithPart()) {
- addColumnsQueried(alias, timeDimColumn);
- }
- }
-
- public void addColumnsQueried(String alias, String column) {
-
- Set<String> cols = tblAliasToColumns.get(alias.toLowerCase());
- if (cols == null) {
- cols = new LinkedHashSet<String>();
- tblAliasToColumns.put(alias.toLowerCase(), cols);
+ qur.addColumnsQueried(alias, timeDimColumn);
}
- cols.add(column);
}
public boolean isCubeMeasure(String col) {
@@ -1116,32 +1107,16 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
return isCubeMeasure(msrname);
}
- public boolean isAggregateExpr(String expr) {
- return aggregateExprs.contains(expr == null ? null : expr.toLowerCase());
- }
-
public boolean hasAggregates() {
- return !aggregateExprs.isEmpty() || getExprCtx().hasAggregates();
- }
-
- public String getAlias(String expr) {
- return exprToAlias.get(expr);
- }
-
- public String getSelectAlias(int index) {
- return selectAliases.get(index);
- }
-
- public String getSelectFinalAlias(int index) {
- return selectFinalAliases.get(index);
- }
-
- public Map<String, String> getExprToAliasMap() {
- return exprToAlias;
- }
-
- public void addAggregateExpr(String expr) {
- aggregateExprs.add(expr);
+ if (getExprCtx().hasAggregates()) {
+ return true;
+ }
+ for (QueriedPhraseContext qur : queriedPhrases) {
+ if (qur.isAggregate()) {
+ return true;
+ }
+ }
+ return false;
}
public void setJoinCond(QBJoinTree qb, String cond) {
@@ -1168,19 +1143,6 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
return "";
}
- public void addExprToAlias(ASTNode expr, ASTNode alias) {
- exprToAlias.put(HQLParser.getString(expr).trim(), alias.getText().toLowerCase());
- }
-
- public void addSelectAlias(String alias, String spacedAlias) {
- selectAliases.add(alias);
- if (!StringUtils.isBlank(spacedAlias)) {
- selectFinalAliases.add("`" + spacedAlias + "`");
- } else {
- selectFinalAliases.add(alias);
- }
- }
-
public Set<Aliased<Dimension>> getOptionalDimensions() {
return optionalDimensionMap.keySet();
}
@@ -1230,17 +1192,6 @@ public class CubeQueryContext implements TrackQueriedColumns, QueryAST {
}
}
- /**
- * @return the queriedDimAttrs
- */
- public Set<String> getQueriedDimAttrs() {
- return queriedDimAttrs;
- }
-
- public void addQueriedDimAttrs(Set<String> dimAttrs) {
- queriedDimAttrs.addAll(dimAttrs);
- }
-
public void addQueriedMsrs(Set<String> msrs) {
queriedMsrs.addAll(msrs);
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/DenormalizationResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/DenormalizationResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/DenormalizationResolver.java
index ab1710d..40ed387 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/DenormalizationResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/DenormalizationResolver.java
@@ -360,7 +360,7 @@ public class DenormalizationResolver implements ContextRewriter {
}
if (cubeql.getCandidateFacts().size() == 0) {
throw new LensException(LensCubeErrorCode.NO_FACT_HAS_COLUMN.getLensErrorInfo(),
- cubeql.getColumnsQueried(cubeql.getCube().getName()).toString());
+ cubeql.getColumnsQueriedForTable(cubeql.getCube().getName()).toString());
}
cubeql.pruneCandidateFactSet(CandidateTablePruneCode.COLUMN_NOT_FOUND);
}
@@ -382,7 +382,7 @@ public class DenormalizationResolver implements ContextRewriter {
if (cubeql.getCandidateDimTables().get(dim).size() == 0) {
throw new LensException(LensCubeErrorCode.NO_DIM_HAS_COLUMN.getLensErrorInfo(),
- dim.toString(), cubeql.getColumnsQueried(dim.getName()).toString());
+ dim.toString(), cubeql.getColumnsQueriedForTable(dim.getName()).toString());
}
}
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/ExpressionResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/ExpressionResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/ExpressionResolver.java
index 5adea6c..60dacdb 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/ExpressionResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/ExpressionResolver.java
@@ -59,8 +59,7 @@ class ExpressionResolver implements ContextRewriter {
private Set<ExprSpecContext> allExprs = new LinkedHashSet<ExprSpecContext>();
private Set<CandidateTable> directlyAvailableIn = new HashSet<CandidateTable>();
@Getter
- private Map<CandidateTable, Set<ExprSpecContext>> evaluableExpressions =
- new HashMap<CandidateTable, Set<ExprSpecContext>>();
+ private Map<CandidateTable, Set<ExprSpecContext>> evaluableExpressions = new HashMap<>();
private boolean hasMeasures = false;
public boolean hasMeasures() {
@@ -197,16 +196,13 @@ class ExpressionResolver implements ContextRewriter {
}
}
- static class ExprSpecContext implements TrackQueriedColumns {
+ static class ExprSpecContext extends TracksQueriedColumns {
private Set<ExprSpec> exprSpecs = new LinkedHashSet<>();
@Getter
@Setter
private ASTNode finalAST;
@Getter
private Set<Dimension> exprDims = new HashSet<>();
- // for each expression store alias to columns queried
- @Getter
- private Map<String, Set<String>> tblAliasToColumns = new HashMap<>();
ExprSpecContext(ExprSpec exprSpec, CubeQueryContext cubeql) throws LensException {
// replaces table names in expression with aliases in the query
@@ -224,14 +220,6 @@ class ExpressionResolver implements ContextRewriter {
AliasReplacer.extractTabAliasForCol(cubeql, this);
finalAST = AliasReplacer.replaceAliases(finalAST, 0, cubeql.getColToTableAlias());
}
- public void addColumnsQueried(String alias, String column) {
- Set<String> cols = tblAliasToColumns.get(alias.toLowerCase());
- if (cols == null) {
- cols = new HashSet<String>();
- tblAliasToColumns.put(alias.toLowerCase(), cols);
- }
- cols.add(column);
- }
void resolveColumns(CubeQueryContext cubeql) throws LensException {
// finds all columns and table aliases in the expression
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/GroupbyResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/GroupbyResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/GroupbyResolver.java
index 8beeb9d..26ae1e7 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/GroupbyResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/GroupbyResolver.java
@@ -21,7 +21,6 @@ package org.apache.lens.cube.parse;
import static org.apache.hadoop.hive.ql.parse.HiveParser.*;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
import org.apache.lens.cube.metadata.AbstractBaseTable;
@@ -54,7 +53,7 @@ class GroupbyResolver implements ContextRewriter {
CubeQueryConfUtil.DEFAULT_ENABLE_GROUP_BY_TO_SELECT);
}
- private void promoteSelect(CubeQueryContext cubeql, List<String> nonMsrNonAggSelExprsWithoutAlias,
+ private void promoteSelect(CubeQueryContext cubeql, List<SelectPhraseContext> selectExprs,
List<String> groupByExprs) throws LensException {
if (!selectPromotionEnabled) {
return;
@@ -68,10 +67,10 @@ class GroupbyResolver implements ContextRewriter {
// each selected column, if it is not a cube measure, and does not have
// aggregation on the column, then it is added to group by columns.
if (cubeql.hasAggregates()) {
- for (String expr : nonMsrNonAggSelExprsWithoutAlias) {
-
+ for (SelectPhraseContext sel : selectExprs) {
+ String expr = sel.getExprWithoutAlias();
if (!groupByExprs.contains(expr)) {
- if (!cubeql.isAggregateExpr(expr)) {
+ if (!sel.isAggregate()) {
ASTNode exprAST = HQLParser.parseExpr(expr);
ASTNode groupbyAST = cubeql.getGroupByAST();
if (!isConstantsUsed(exprAST)) {
@@ -116,23 +115,21 @@ class GroupbyResolver implements ContextRewriter {
return false;
}
- private void promoteGroupby(CubeQueryContext cubeql, List<String> selectExprs, List<String> groupByExprs)
+ private void promoteGroupby(CubeQueryContext cubeql, List<SelectPhraseContext> selectExprs,
+ List<String> groupByExprs)
throws LensException {
if (!groupbyPromotionEnabled) {
return;
}
- for (String expr : selectExprs) {
- expr = getExpressionWithoutAlias(cubeql, expr);
- if (!cubeql.isAggregateExpr(expr)) {
- log.info("Not promoting groupby expression to select, since there are expression projected");
- return;
- }
+ if (selectExprs.size() > 0) {
+ log.info("Not promoting groupby expression to select, since there are expression projected");
+ return;
}
int index = 0;
for (String expr : groupByExprs) {
- if (!contains(cubeql, selectExprs, expr)) {
+ if (!contains(selectExprs, expr)) {
ASTNode exprAST = HQLParser.parseExpr(expr);
addChildAtIndex(index, cubeql.getSelectAST(), exprAST);
index++;
@@ -158,33 +155,21 @@ class GroupbyResolver implements ContextRewriter {
public void rewriteContext(CubeQueryContext cubeql) throws LensException {
// Process Aggregations by making sure that all group by keys are projected;
// and all projection fields are added to group by keylist;
- List<String> selectExprs = new ArrayList<String>();
- String[] sel = getExpressions(cubeql.getSelectAST(), cubeql).toArray(new String[]{});
- for (String s : sel) {
- selectExprs.add(s.trim());
- }
- List<String> groupByExprs = new ArrayList<String>();
+ List<SelectPhraseContext> selectExprs = getSelectNonAggregateNonMeasureExpressions(cubeql);
+ List<String> groupByExprs = new ArrayList<>();
if (cubeql.getGroupByString() != null) {
- String[] gby = getExpressions(cubeql.getGroupByAST(), cubeql).toArray(new String[]{});
+ String[] gby = getGroupbyExpressions(cubeql.getGroupByAST()).toArray(new String[]{});
for (String g : gby) {
groupByExprs.add(g.trim());
}
}
- promoteSelect(cubeql, getNonMsrNonAggSelExprsWithoutAlias(cubeql.getSelectAST(), cubeql), groupByExprs);
+ promoteSelect(cubeql, selectExprs, groupByExprs);
promoteGroupby(cubeql, selectExprs, groupByExprs);
}
- private String getExpressionWithoutAlias(CubeQueryContext cubeql, String sel) {
- String alias = cubeql.getAlias(sel);
- if (alias != null) {
- sel = sel.substring(0, (sel.length() - alias.length())).trim();
- }
- return sel;
- }
-
- private boolean contains(CubeQueryContext cubeql, List<String> selExprs, String expr) {
- for (String sel : selExprs) {
- sel = getExpressionWithoutAlias(cubeql, sel);
+ private boolean contains(List<SelectPhraseContext> selExprs, String expr) {
+ for (SelectPhraseContext selExpr : selExprs) {
+ String sel = selExpr.getExprWithoutAlias();
if (sel.equals(expr)) {
return true;
}
@@ -192,72 +177,32 @@ class GroupbyResolver implements ContextRewriter {
return false;
}
- /**
- * @param selectASTNode a select AST Node
- * @param cubeQueryCtx
- * @return List of non measure and non aggregate select expressions in string format without aliases
- */
- private List<String> getNonMsrNonAggSelExprsWithoutAlias(final ASTNode selectASTNode, CubeQueryContext cubeQueryCtx) {
-
- List<String> nonMsrNonAggSelExprsWithoutAlias = new LinkedList<String>();
- List<ASTNode> nonMsrNonAggSelASTChildren = filterNonMsrNonAggSelectASTChildren(selectASTNode, cubeQueryCtx);
-
- for (ASTNode nonMsrNonAggSelASTChild : nonMsrNonAggSelASTChildren) {
+ private List<SelectPhraseContext> getSelectNonAggregateNonMeasureExpressions(CubeQueryContext cubeql) {
- /* Assuming all children of SelectASTNode are SELECT Expression AST Nodes only.
- Refer:https://reviews.apache.org/r/29422/#comment109498 for more details.
- Order of Children of select expression AST Node => Index 0: Select Expression Without Alias, Index 1: Alias */
+ List<SelectPhraseContext> list = new ArrayList<>();
- ASTNode selExprWithoutAlias = (ASTNode) nonMsrNonAggSelASTChild.getChildren().get(0);
- String result = HQLParser.getString(selExprWithoutAlias);
- nonMsrNonAggSelExprsWithoutAlias.add(result);
-
- }
- return nonMsrNonAggSelExprsWithoutAlias;
- }
-
- /**
- * @param selectASTNode a select ASTNode
- * @param cubeQueryCtx
- * @return list of selectASTNode Children which does not contain a measure or an aggregate. Empty list is returned
- * when selectASTNode is not a Select AST Node. Empty list is returned when there are no non measure and non aggregate
- * children nodes present in select AST.
- */
- private List<ASTNode> filterNonMsrNonAggSelectASTChildren(final ASTNode selectASTNode,
- CubeQueryContext cubeQueryCtx) {
- List<ASTNode> nonMsrNonAggSelASTChildren = new LinkedList<ASTNode>();
-
- if (!HQLParser.isSelectASTNode(selectASTNode)) {
- return nonMsrNonAggSelASTChildren;
- }
-
- for (int i = 0; i < selectASTNode.getChildCount(); i++) {
- ASTNode childNode = (ASTNode) selectASTNode.getChild(i);
- if (hasMeasure(childNode, cubeQueryCtx) || hasAggregate(childNode, cubeQueryCtx)) {
+ for (SelectPhraseContext sel : cubeql.getSelectPhrases()) {
+ if (hasMeasure(sel.getExprAST(), cubeql)) {
+ continue;
+ }
+ if (hasAggregate(sel.getExprAST(), cubeql)) {
continue;
}
- nonMsrNonAggSelASTChildren.add(childNode);
+ list.add(sel);
}
- return nonMsrNonAggSelASTChildren;
+ return list;
}
- private List<String> getExpressions(ASTNode node, CubeQueryContext cubeql) {
+ private List<String> getGroupbyExpressions(ASTNode node) {
- List<String> list = new ArrayList<String>();
+ List<String> list = new ArrayList<>();
if (node == null) {
return list;
}
for (int i = 0; i < node.getChildCount(); i++) {
- ASTNode child = (ASTNode) node.getChild(i);
- if (hasMeasure(child, cubeql)) {
- continue;
- }
- if (hasAggregate(child, cubeql)) {
- continue;
- }
list.add(HQLParser.getString((ASTNode) node.getChild(i)));
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
index b3547db..979c24b 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
@@ -111,17 +111,18 @@ class MultiFactHQLContext extends SimpleHQLContext {
}
if (selectToFactIndex.get(i).size() == 1) {
select.append("mq").append(selectToFactIndex.get(i).get(0)).append(".")
- .append(query.getSelectAlias(i)).append(" ");
+ .append(query.getSelectPhrases().get(i).getSelectAlias()).append(" ");
} else {
select.append("COALESCE(");
String sep = "";
for (Integer factIndex : selectToFactIndex.get(i)) {
- select.append(sep).append("mq").append(factIndex).append(".").append(query.getSelectAlias(i));
+ select.append(sep).append("mq").append(factIndex).append(".").append(
+ query.getSelectPhrases().get(i).getSelectAlias());
sep = ", ";
}
select.append(") ");
}
- select.append(query.getSelectFinalAlias(i));
+ select.append(query.getSelectPhrases().get(i).getFinalAlias());
if (i != query.getSelectAST().getChildCount() - 1) {
select.append(", ");
}
@@ -152,7 +153,7 @@ class MultiFactHQLContext extends SimpleHQLContext {
fromBuilder.append(" on ");
Iterator<Integer> dimIter = fact.getDimFieldIndices().iterator();
while (dimIter.hasNext()) {
- String dim = query.getSelectAlias(dimIter.next());
+ String dim = query.getSelectPhrases().get(dimIter.next()).getSelectAlias();
fromBuilder.append(getMultiFactJoinCondition(aliasCount, dim));
if (dimIter.hasNext()) {
fromBuilder.append(" AND ");
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/QueriedPhraseContext.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/QueriedPhraseContext.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/QueriedPhraseContext.java
new file mode 100644
index 0000000..11eb8f7
--- /dev/null
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/QueriedPhraseContext.java
@@ -0,0 +1,186 @@
+/**
+ * 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.lens.cube.parse;
+
+import java.util.*;
+
+import org.apache.lens.cube.metadata.MetastoreConstants;
+import org.apache.lens.cube.metadata.TimeRange;
+import org.apache.lens.server.api.error.LensException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.hive.ql.parse.ASTNode;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Slf4j
+class QueriedPhraseContext extends TracksQueriedColumns implements TrackQueriedCubeFields {
+ private final ASTNode exprAST;
+ private Boolean aggregate;
+ private String expr;
+ private final Set<String> queriedDimAttrs = new HashSet<>();
+ private final Set<String> queriedMsrs = new HashSet<>();
+ private final Set<String> queriedExprColumns = new HashSet<>();
+ private final Set<String> columns = new HashSet<>();
+
+ void setNotAggregate() {
+ this.aggregate = false;
+ }
+
+ boolean isAggregate() {
+ if (aggregate == null) {
+ aggregate = HQLParser.hasAggregate(exprAST);
+ }
+ return aggregate;
+ }
+
+ String getExpr() {
+ if (expr == null) {
+ expr = HQLParser.getString(getExprAST()).trim();
+ }
+ return expr;
+ }
+
+ void updateExprs() {
+ expr = HQLParser.getString(getExprAST()).trim();
+ }
+
+ @Override
+ public void addQueriedDimAttr(String attrName) {
+ queriedDimAttrs.add(attrName);
+ columns.add(attrName);
+ }
+
+ @Override
+ public void addQueriedMsr(String msrName) {
+ queriedMsrs.add(msrName);
+ columns.add(msrName);
+ }
+
+ @Override
+ public void addQueriedExprColumn(String exprCol) {
+ queriedExprColumns.add(exprCol);
+ columns.add(exprCol);
+ }
+
+ public boolean hasMeasures(CubeQueryContext cubeQl) {
+ if (!queriedMsrs.isEmpty()) {
+ return true;
+ }
+ if (!queriedExprColumns.isEmpty()) {
+ for (String exprCol : queriedExprColumns) {
+ if (cubeQl.getQueriedExprsWithMeasures().contains(exprCol)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isEvaluable(CubeQueryContext cubeQl, CandidateFact cfact) throws LensException {
+ // all measures of the queried phrase should be present
+ for (String msr : queriedMsrs) {
+ if (!checkForColumnExistsAndValidForRange(cfact, msr, cubeQl)) {
+ return false;
+ }
+ }
+ // all expression columns should be evaluable
+ for (String exprCol : queriedExprColumns) {
+ if (!cubeQl.getExprCtx().isEvaluable(exprCol, cfact)) {
+ log.info("expression {} is not evaluable in fact table:{}", expr, cfact);
+ return false;
+ }
+ }
+ // all dim-attributes should be present.
+ for (String col : queriedDimAttrs) {
+ if (!cfact.getColumns().contains(col.toLowerCase())) {
+ // check if it available as reference
+ if (!cubeQl.getDeNormCtx().addRefUsage(cfact, col, cubeQl.getCube().getName())) {
+ log.info("column {} is not available in fact table:{} ", col, cfact);
+ return false;
+ }
+ } else if (!isFactColumnValidForRange(cubeQl, cfact, col)) {
+ log.info("column {} is not available in range queried in fact {}", col, cfact);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isColumnAvailableInRange(final TimeRange range, Date startTime, Date endTime) {
+ return (isColumnAvailableFrom(range.getFromDate(), startTime)
+ && isColumnAvailableTill(range.getToDate(), endTime));
+ }
+
+ public static boolean isColumnAvailableFrom(@NonNull final Date date, Date startTime) {
+ return (startTime == null) || date.equals(startTime) || date.after(startTime);
+ }
+
+ public static boolean isColumnAvailableTill(@NonNull final Date date, Date endTime) {
+ return (endTime == null) || date.equals(endTime) || date.before(endTime);
+ }
+
+ public static boolean isFactColumnValidForRange(CubeQueryContext cubeql, CandidateTable cfact, String col) {
+ for(TimeRange range : cubeql.getTimeRanges()) {
+ if (!isColumnAvailableInRange(range, getFactColumnStartTime(cfact, col), getFactColumnEndTime(cfact, col))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static Date getFactColumnStartTime(CandidateTable table, String factCol) {
+ Date startTime = null;
+ if (table instanceof CandidateFact) {
+ for (String key : ((CandidateFact) table).fact.getProperties().keySet()) {
+ if (key.contains(MetastoreConstants.FACT_COL_START_TIME_PFX)) {
+ String propCol = StringUtils.substringAfter(key, MetastoreConstants.FACT_COL_START_TIME_PFX);
+ if (factCol.equals(propCol)) {
+ startTime = ((CandidateFact) table).fact.getDateFromProperty(key, false, true);
+ }
+ }
+ }
+ }
+ return startTime;
+ }
+
+ public static Date getFactColumnEndTime(CandidateTable table, String factCol) {
+ Date endTime = null;
+ if (table instanceof CandidateFact) {
+ for (String key : ((CandidateFact) table).fact.getProperties().keySet()) {
+ if (key.contains(MetastoreConstants.FACT_COL_END_TIME_PFX)) {
+ String propCol = StringUtils.substringAfter(key, MetastoreConstants.FACT_COL_END_TIME_PFX);
+ if (factCol.equals(propCol)) {
+ endTime = ((CandidateFact) table).fact.getDateFromProperty(key, false, true);
+ }
+ }
+ }
+ }
+ return endTime;
+ }
+
+ static boolean checkForColumnExistsAndValidForRange(CandidateTable table, String column, CubeQueryContext cubeql) {
+ return (table.getColumns().contains(column) && isFactColumnValidForRange(cubeql, table, column));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/SelectPhraseContext.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/SelectPhraseContext.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/SelectPhraseContext.java
new file mode 100644
index 0000000..b6702e5
--- /dev/null
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/SelectPhraseContext.java
@@ -0,0 +1,51 @@
+/**
+ * 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.lens.cube.parse;
+
+import org.apache.hadoop.hive.ql.parse.ASTNode;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+class SelectPhraseContext extends QueriedPhraseContext {
+ private String actualAlias;
+ private String selectAlias;
+ private String finalAlias;
+ private String exprWithoutAlias;
+
+ public SelectPhraseContext(ASTNode selectExpr) {
+ super(selectExpr);
+ }
+
+ String getExprWithoutAlias() {
+ if (exprWithoutAlias == null) {
+ //Order of Children of select expression AST Node => Index 0: Select Expression Without Alias, Index 1: Alias */
+ exprWithoutAlias = HQLParser.getString((ASTNode) getExprAST().getChild(0)).trim();
+ }
+ return exprWithoutAlias;
+ }
+
+ void updateExprs() {
+ super.updateExprs();
+ exprWithoutAlias = HQLParser.getString((ASTNode) getExprAST().getChild(0)).trim();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRangeChecker.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRangeChecker.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRangeChecker.java
index ca176ee..89b50f5 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRangeChecker.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRangeChecker.java
@@ -139,13 +139,13 @@ public class TimeRangeChecker implements ContextRewriter {
private void doColLifeValidation(CubeQueryContext cubeql) throws LensException,
ColUnAvailableInTimeRangeException {
- Set<String> cubeColumns = cubeql.getColumnsQueried(cubeql.getCube().getName());
+ Set<String> cubeColumns = cubeql.getColumnsQueriedForTable(cubeql.getCube().getName());
if (cubeColumns == null || cubeColumns.isEmpty()) {
// Query doesn't have any columns from cube
return;
}
- for (String col : cubeql.getColumnsQueried(cubeql.getCube().getName())) {
+ for (String col : cubeql.getColumnsQueriedForTable(cubeql.getCube().getName())) {
CubeColumn column = cubeql.getCube().getColumnByName(col);
for (TimeRange range : cubeql.getTimeRanges()) {
if (column == null) {
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedColumns.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedColumns.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedColumns.java
index b65ac26..45d59df 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedColumns.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedColumns.java
@@ -22,6 +22,33 @@ import java.util.Map;
import java.util.Set;
interface TrackQueriedColumns {
+
+ /**
+ * Get tblAlias to column
+ * @return map of tblAliasToColumns
+ */
Map<String, Set<String>> getTblAliasToColumns();
- void addColumnsQueried(String alias, String column);
+
+ /**
+ * Get columns queried by tblAlias
+ *
+ * @param tblAlias tbl alias name
+ *
+ * @return set of column names
+ */
+ Set<String> getColumnsQueried(String tblAlias);
+
+ /**
+ * Add given table alias and column
+ * @param tblAlias Table alias
+ * @param column column
+ */
+ void addColumnsQueried(String tblAlias, String column);
+
+ /**
+ * Add given map of tblAliasToColumns.
+ *
+ * @param tblAliasToColumns map of tblAliasToColumns
+ */
+ void addColumnsQueried(Map<String, Set<String>> tblAliasToColumns);
}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedCubeFields.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedCubeFields.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedCubeFields.java
new file mode 100644
index 0000000..eafbb0e
--- /dev/null
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/TrackQueriedCubeFields.java
@@ -0,0 +1,66 @@
+/**
+ * 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.lens.cube.parse;
+
+import java.util.Set;
+
+interface TrackQueriedCubeFields {
+
+ /**
+ * Get queried dim attributes
+ *
+ * @return set of dim attribute names
+ */
+ Set<String> getQueriedDimAttrs();
+
+ /**
+ * Get queried measures
+ *
+ * @return set of measure names
+ */
+ Set<String> getQueriedMsrs();
+
+ /**
+ * Get queried expr columns
+ *
+ * @return set of expr column names
+ */
+ Set<String> getQueriedExprColumns();
+
+ /**
+ * Add queried dim attribute
+ *
+ * @param attrName attribute name
+ */
+ void addQueriedDimAttr(String attrName);
+
+ /**
+ * Add queried measure
+ *
+ * @param msrName measure name
+ */
+ void addQueriedMsr(String msrName);
+
+ /**
+ * Add queried expression column
+ *
+ * @param exprCol expression column name
+ */
+ void addQueriedExprColumn(String exprCol);
+}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/main/java/org/apache/lens/cube/parse/TracksQueriedColumns.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/TracksQueriedColumns.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/TracksQueriedColumns.java
new file mode 100644
index 0000000..fb16478
--- /dev/null
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/TracksQueriedColumns.java
@@ -0,0 +1,59 @@
+/**
+ * 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.lens.cube.parse;
+
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import lombok.Getter;
+
+abstract class TracksQueriedColumns implements TrackQueriedColumns {
+
+ @Getter
+ private Map<String, Set<String>> tblAliasToColumns = new HashMap<>();
+
+ public void addColumnsQueried(String tblAlias, String column) {
+
+ Set<String> cols = tblAliasToColumns.get(tblAlias.toLowerCase());
+ if (cols == null) {
+ cols = new LinkedHashSet<>();
+ tblAliasToColumns.put(tblAlias.toLowerCase(), cols);
+ }
+ cols.add(column);
+ }
+
+ public void addColumnsQueried(Map<String, Set<String>> tblAliasToColumns) {
+
+ for (Map.Entry<String, Set<String>> entry : tblAliasToColumns.entrySet()) {
+ Set<String> cols = this.tblAliasToColumns.get(entry.getKey());
+ if (cols == null) {
+ cols = new LinkedHashSet<>();
+ this.tblAliasToColumns.put(entry.getKey(), cols);
+ }
+ cols.addAll(entry.getValue());
+ }
+ }
+
+ public Set<String> getColumnsQueried(String tblAlias) {
+ return tblAliasToColumns.get(tblAlias);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lens/blob/2cfb7b09/lens-cube/src/test/java/org/apache/lens/cube/parse/CubeTestSetup.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/test/java/org/apache/lens/cube/parse/CubeTestSetup.java b/lens-cube/src/test/java/org/apache/lens/cube/parse/CubeTestSetup.java
index f7f8af2..0c43cb5 100644
--- a/lens-cube/src/test/java/org/apache/lens/cube/parse/CubeTestSetup.java
+++ b/lens-cube/src/test/java/org/apache/lens/cube/parse/CubeTestSetup.java
@@ -984,6 +984,7 @@ public class CubeTestSetup {
"dim2chain", "id", null, null, null)); // used as key in the chains
cubeDimensions2.add(new ReferencedDimAttribute(new FieldSchema("dim22", "int", "ref dim"), "Dim2 refer",
"dim2chain", "id", null, null, null)); // not used as key in the chains
+ cubeDimensions2.add(new BaseDimAttribute(new FieldSchema("dim13", "string", "basedim")));
cubeDimensions2.add(new BaseDimAttribute(new FieldSchema("userid", "int", "userid")));
cubeDimensions2.add(new BaseDimAttribute(new FieldSchema("xuserid", "int", "userid")));
cubeDimensions2.add(new BaseDimAttribute(new FieldSchema("yuserid", "int", "userid")));
@@ -1232,6 +1233,7 @@ public class CubeTestSetup {
dimensions.add("dim2big2");
dimensions.add("dim2bignew");
dimensions.add("dim11");
+ dimensions.add("dim13");
dimensions.add("dim12");
dimensions.add("dim22");
dimensions.add("d_time");
@@ -1408,6 +1410,7 @@ public class CubeTestSetup {
factColumns.add(new FieldSchema("processing_time", "timestamp", "processing time"));
factColumns.add(new FieldSchema("dim1", "string", "base dim"));
factColumns.add(new FieldSchema("dim11", "string", "base dim"));
+ factColumns.add(new FieldSchema("dim13", "string", "base dim"));
factColumns.add(new FieldSchema("dim12", "string", "base dim"));
factColumns.add(new FieldSchema("dim22", "string", "base dim"));
factColumns.add(new FieldSchema("cityid", "int", "city id"));