You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lens.apache.org by jd...@apache.org on 2015/06/23 12:25:36 UTC
[48/51] [abbrv] incubator-lens git commit: LENS-605 : Fix Candidate
pruning wrt sourcecolumns required for joinchains
LENS-605 : Fix Candidate pruning wrt sourcecolumns required for joinchains
Project: http://git-wip-us.apache.org/repos/asf/incubator-lens/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-lens/commit/5f859118
Tree: http://git-wip-us.apache.org/repos/asf/incubator-lens/tree/5f859118
Diff: http://git-wip-us.apache.org/repos/asf/incubator-lens/diff/5f859118
Branch: refs/heads/current-release-line
Commit: 5f859118c2ea49cc09dd59472d266064d36ca978
Parents: 0cf6c4e
Author: Amareshwari Sriramadasu <am...@gmail.com>
Authored: Mon Jun 22 14:22:13 2015 +0530
Committer: Rajat Khandelwal <ra...@gmail.com>
Committed: Mon Jun 22 14:22:13 2015 +0530
----------------------------------------------------------------------
.../lens/cube/parse/CandidateTableResolver.java | 124 +++++++++++++++----
.../lens/cube/parse/CubeQueryContext.java | 70 ++++++++++-
.../cube/parse/DenormalizationResolver.java | 6 +-
.../lens/cube/parse/ExpressionResolver.java | 27 ++--
.../apache/lens/cube/parse/JoinResolver.java | 4 +-
.../cube/parse/TestDenormalizationResolver.java | 32 ++++-
6 files changed, 218 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5f859118/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 79d6d43..1b5c09a 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
@@ -23,6 +23,9 @@ import java.util.*;
import org.apache.lens.cube.metadata.*;
import org.apache.lens.cube.parse.CandidateTablePruneCause.CandidateTablePruneCode;
import org.apache.lens.cube.parse.CubeQueryContext.OptionalDimCtx;
+import org.apache.lens.cube.parse.CubeQueryContext.QueriedExprColumn;
+import org.apache.lens.cube.parse.ExpressionResolver.ExprSpecContext;
+import org.apache.lens.cube.parse.ExpressionResolver.ExpressionContext;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
@@ -32,6 +35,8 @@ import org.apache.hadoop.hive.ql.ErrorMsg;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
+import com.google.common.collect.Sets;
+
/**
* This resolver prunes the candidate tables for following cases
* <p/>
@@ -493,39 +498,127 @@ class CandidateTableResolver implements ContextRewriter {
return;
}
// check for source columns for denorm columns
- Map<CandidateTable, Collection<String>> removedCandidates = new HashMap<CandidateTable, Collection<String>>();
+ Map<Dimension, Set<CandidateTable>> removedCandidates = new HashMap<Dimension, Set<CandidateTable>>();
for (Map.Entry<Dimension, OptionalDimCtx> optdimEntry : cubeql.getOptionalDimensionMap().entrySet()) {
Dimension dim = optdimEntry.getKey();
OptionalDimCtx optdim = optdimEntry.getValue();
Iterator<CandidateTable> iter = optdim.requiredForCandidates.iterator();
+ // remove candidates from each optional dim if the dimension is not reachable from candidate
+ Set<CandidateTable> cTableSet = Sets.newHashSet();
+ removedCandidates.put(dim, cTableSet);
while (iter.hasNext()) {
CandidateTable candidate = iter.next();
boolean remove = false;
if (cubeql.getAutoJoinCtx().getJoinPathFromColumns().get(dim) == null) {
- LOG.info("Removing candidate" + candidate + " from requiredForCandidates of" + dim + ", as no join paths"
+ LOG.info("Removing candidate " + candidate + " from requiredForCandidates of " + dim + ", as no join paths"
+ " exist");
remove = true;
- removedCandidates.put(candidate, optdim.colQueried);
} else {
List<String> colSet = cubeql.getAutoJoinCtx().getJoinPathFromColumns().get(dim).get(candidate.getBaseTable());
if (!checkForColumnExists(candidate, colSet)) {
- LOG.info("Removing candidate" + candidate + " from requiredForCandidates of" + dim + ", as columns:"
+ LOG.info("Removing candidate " + candidate + " from requiredForCandidates of " + dim + ", as columns:"
+ colSet + " do not exist");
remove = true;
- removedCandidates.put(candidate, colSet);
}
}
if (remove) {
iter.remove();
+ cTableSet.add(candidate);
}
}
}
- Set<CandidateTable> candidatesReachableThroughRefs = new HashSet<CandidateTable>();
+ // For each ref column required in cube query
+ // remove candidates which are not reachable
+ // For example:
+ // CTable | Col1 | Col2
+ // F1 | reachable through D1 | Not reachable
+ // F2 | Reachable through D2 | Reachable through D5
+ // F3 | Not reachable | Not reachable
+ // F4 | Not reachable | Reachable through D6
+ // F5 | Directly available | Directly available
+ // F6 | Directly available | Not reachable
+ // F3 and F4 will get pruned while iterating over col1 and F1, F6 will get pruned while iterating over col2.
+ for (Map.Entry<String, Set<Dimension>> dimColEntry : cubeql.getRefColToDim().entrySet()) {
+ Set<CandidateTable> candidatesReachableThroughRefs = new HashSet<CandidateTable>();
+ String col = dimColEntry.getKey();
+ Set<Dimension> dimSet = dimColEntry.getValue();
+ for (Dimension dim : dimSet) {
+ OptionalDimCtx optdim = cubeql.getOptionalDimensionMap().get(dim);
+ candidatesReachableThroughRefs.addAll(optdim.requiredForCandidates);
+ }
+ for (Dimension dim : dimSet) {
+ for (CandidateTable candidate : removedCandidates.get(dim)) {
+ if (!candidatesReachableThroughRefs.contains(candidate)) {
+ if (candidate instanceof CandidateFact) {
+ if (cubeql.getCandidateFacts().contains(candidate)) {
+ LOG.info("Not considering fact:" + candidate + " as its required optional dims are not reachable");
+ cubeql.getCandidateFacts().remove(candidate);
+ cubeql.addFactPruningMsgs(((CandidateFact) candidate).fact,
+ CandidateTablePruneCause.columnNotFound(col));
+ }
+ } else if (cubeql.getCandidateDimTables().containsKey(((CandidateDim) candidate).getBaseTable())) {
+ LOG.info("Not considering dimtable:" + candidate + " as its required optional dims are not reachable");
+ cubeql.getCandidateDimTables().get(((CandidateDim) candidate).getBaseTable()).remove(candidate);
+ cubeql.addDimPruningMsgs((Dimension) candidate.getBaseTable(), (CubeDimensionTable) candidate.getTable(),
+ CandidateTablePruneCause.columnNotFound(col));
+ }
+ }
+ }
+ }
+ }
+
+ // For each expression column required in cube query
+ // remove candidates in which expressions are not evaluable - for expression column all dimensions accessed in
+ // expression should be reachable from candidate.
+ // For example:
+ // CTable | Col1 | Col2
+ // F1 | evaluable through D1, D3 | Not evaluable
+ // F2 | evaluable through D2, D4 | evaluable through D5
+ // F3 | Not evaluable | Not evaluable
+ // F4 | Not evaluable | evaluable through D6
+ // F5 | Directly available | Directly available
+ // F6 | Directly available | Not evaluable
+ for (Map.Entry<QueriedExprColumn, Set<Dimension>> exprColEntry : cubeql.getExprColToDim().entrySet()) {
+ QueriedExprColumn col = exprColEntry.getKey();
+ Set<Dimension> dimSet = exprColEntry.getValue();
+ ExpressionContext ec = cubeql.getExprCtx().getExpressionContext(col.getExprCol(), col.getAlias());
+ for (Dimension dim : dimSet) {
+ for (CandidateTable candidate : removedCandidates.get(dim)) {
+ // check if evaluable expressions of this candidate are no more evaluable because dimension is not reachable
+ // if no evaluable expressions exist, then remove the candidate
+ Iterator<ExprSpecContext> escIter = ec.getEvaluableExpressions().get(candidate).iterator();
+ while (escIter.hasNext()) {
+ ExprSpecContext esc = escIter.next();
+ if (esc.getExprDims().contains(dim)) {
+ escIter.remove();
+ }
+ }
+ if (cubeql.getExprCtx().isEvaluable(col.getExprCol(), candidate)) {
+ // candidate has other evaluable expressions
+ continue;
+ }
+ if (candidate instanceof CandidateFact) {
+ if (cubeql.getCandidateFacts().contains(candidate)) {
+ LOG.info("Not considering fact:" + candidate + " as is not reachable through any optional dim");
+ cubeql.getCandidateFacts().remove(candidate);
+ cubeql.addFactPruningMsgs(((CandidateFact) candidate).fact,
+ CandidateTablePruneCause.expressionNotEvaluable(col.getExprCol()));
+ }
+ } else if (cubeql.getCandidateDimTables().containsKey(((CandidateDim) candidate).getBaseTable())) {
+ LOG.info("Not considering dimtable:" + candidate + " as is not reachable through any optional dim");
+ cubeql.getCandidateDimTables().get(((CandidateDim) candidate).getBaseTable()).remove(candidate);
+ cubeql.addDimPruningMsgs((Dimension) candidate.getBaseTable(), (CubeDimensionTable) candidate.getTable(),
+ CandidateTablePruneCause.expressionNotEvaluable(col.getExprCol()));
+ }
+ }
+ }
+ }
+
+ // remove optional dims which are not required any more.
Set<Dimension> tobeRemoved = new HashSet<Dimension>();
for (Map.Entry<Dimension, OptionalDimCtx> optdimEntry : cubeql.getOptionalDimensionMap().entrySet()) {
Dimension dim = optdimEntry.getKey();
OptionalDimCtx optdim = optdimEntry.getValue();
- candidatesReachableThroughRefs.addAll(optdim.requiredForCandidates);
if ((!optdim.colQueried.isEmpty() && optdim.requiredForCandidates.isEmpty()) && !optdim.isRequiredInJoinChain) {
LOG.info("Not considering optional dimension " + dim + " as all requiredForCandidates are removed");
tobeRemoved.add(dim);
@@ -534,23 +627,6 @@ class CandidateTableResolver implements ContextRewriter {
for (Dimension dim : tobeRemoved) {
removeOptionalDim(cubeql, dim);
}
- for (CandidateTable candidate : removedCandidates.keySet()) {
- if (!candidatesReachableThroughRefs.contains(candidate)) {
- if (candidate instanceof CandidateFact) {
- if (cubeql.getCandidateFacts().contains(candidate)) {
- LOG.info("Not considering fact:" + candidate + " as is not reachable through any optional dim");
- cubeql.getCandidateFacts().remove(candidate);
- cubeql.addFactPruningMsgs(((CandidateFact) candidate).fact,
- CandidateTablePruneCause.columnNotFound(removedCandidates.get(candidate)));
- }
- } else if (cubeql.getCandidateDimTables().containsKey(((CandidateDim) candidate).getBaseTable())) {
- LOG.info("Not considering dimtable:" + candidate + " as is not reachable through any optional dim");
- cubeql.getCandidateDimTables().get(((CandidateDim) candidate).getBaseTable()).remove(candidate);
- cubeql.addDimPruningMsgs((Dimension) candidate.getBaseTable(), (CubeDimensionTable) candidate.getTable(),
- CandidateTablePruneCause.columnNotFound(removedCandidates.get(candidate)));
- }
- }
- }
}
private void resolveCandidateDimTables(CubeQueryContext cubeql) throws SemanticException {
http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5f859118/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 33b1a62..57c075c 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
@@ -45,7 +45,13 @@ import org.apache.hadoop.hive.ql.parse.*;
import org.codehaus.jackson.map.ObjectMapper;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+
+import lombok.AllArgsConstructor;
+
+import lombok.Data;
+
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -346,11 +352,45 @@ public class CubeQueryContext implements TrackQueriedColumns {
return partsQueried;
}
+ // map of ref column in query to set of Dimension that have the column - which are added as optional dims
+ @Getter
+ private Map<String, Set<Dimension>> refColToDim = Maps.newHashMap();
+
+ public void updateRefColDim(String col, Dimension dim) {
+ Set<Dimension> refDims = refColToDim.get(col.toLowerCase());
+ if (refDims == null) {
+ refDims = Sets.newHashSet();
+ refColToDim.put(col.toLowerCase(), refDims);
+ }
+ refDims.add(dim);
+ }
+
+ @Data
+ @AllArgsConstructor
+ static class QueriedExprColumn {
+ private String exprCol;
+ private String alias;
+ }
+ // map of expression column in query to set of Dimension that are accessed in the expression column - which are added
+ // as optional dims
+ @Getter
+ private Map<QueriedExprColumn, Set<Dimension>> exprColToDim = Maps.newHashMap();
+
+ public void updateExprColDim(String tblAlias, String col, Dimension dim) {
+
+ QueriedExprColumn qexpr = new QueriedExprColumn(col, tblAlias);
+ Set<Dimension> exprDims = exprColToDim.get(qexpr);
+ if (exprDims == null) {
+ exprDims = Sets.newHashSet();
+ exprColToDim.put(qexpr, exprDims);
+ }
+ exprDims.add(dim);
+ }
+
// Holds the context of optional dimension
// A dimension is optional if it is not queried directly by the user, but is
// required by a candidate table to get a denormalized field from reference
// or required in a join chain
-
@ToString
static class OptionalDimCtx {
OptionalDimCtx() {
@@ -361,8 +401,22 @@ public class CubeQueryContext implements TrackQueriedColumns {
boolean isRequiredInJoinChain = false;
}
- public void addOptionalDimTable(String alias, CandidateTable candidate, boolean isRequiredInJoin, String... cols)
- throws SemanticException {
+ public void addOptionalJoinDimTable(String alias, boolean isRequired) throws SemanticException {
+ addOptionalDimTable(alias, null, isRequired, null, false, (String[])null);
+ }
+
+ public void addOptionalExprDimTable(String dimAlias, String queriedExpr, String srcTableAlias,
+ CandidateTable candidate, String... cols) throws SemanticException {
+ addOptionalDimTable(dimAlias, candidate, false, queriedExpr, false, srcTableAlias, cols);
+ }
+
+ public void addOptionalDimTable(String alias, CandidateTable candidate, boolean isRequiredInJoin, String cubeCol,
+ boolean isRef, String... cols) throws SemanticException {
+ addOptionalDimTable(alias, candidate, isRequiredInJoin, cubeCol, true, null, cols);
+ }
+
+ private void addOptionalDimTable(String alias, CandidateTable candidate, boolean isRequiredInJoin, String cubeCol,
+ boolean isRef, String tableAlias, String... cols) throws SemanticException {
alias = alias.toLowerCase();
try {
if (!addQueriedTable(alias, true)) {
@@ -380,10 +434,18 @@ public class CubeQueryContext implements TrackQueriedColumns {
}
optDim.requiredForCandidates.add(candidate);
}
+ if (cubeCol != null) {
+ if (isRef) {
+ updateRefColDim(cubeCol, dim);
+ } else {
+ updateExprColDim(tableAlias, cubeCol, dim);
+ }
+ }
if (!optDim.isRequiredInJoinChain) {
optDim.isRequiredInJoinChain = isRequiredInJoin;
}
- LOG.info("Adding optional dimension:" + dim + " optDim:" + optDim);
+ LOG.info("Adding optional dimension:" + dim + " optDim:" + optDim
+ + (cubeCol == null ? "" : " for column:" + cubeCol + " isRef:" + isRef));
} catch (HiveException e) {
throw new SemanticException(e);
}
http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5f859118/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 3ed94fa..075cdb4 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
@@ -152,11 +152,13 @@ public class DenormalizationResolver implements ContextRewriter {
refCols.add(refer);
// Add to optional tables
if (refer.col.isChainedColumn()) {
- cubeql.addOptionalDimTable(refer.col.getChainName(), table, false, refer.col.getRefColumn());
+ cubeql.addOptionalDimTable(refer.col.getChainName(), table, false, refer.col.getName(), true,
+ refer.col.getRefColumn());
} else {
for (TableReference reference : refer.col.getReferences()) {
- cubeql.addOptionalDimTable(reference.getDestTable(), table, false, reference.getDestColumn());
+ cubeql.addOptionalDimTable(reference.getDestTable(), table, false, refer.col.getName(), true,
+ reference.getDestColumn());
}
}
return true;
http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5f859118/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 8e199ea..b2997dd 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
@@ -68,6 +68,7 @@ class ExpressionResolver implements ContextRewriter {
@Getter
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 boolean hasMeasures = false;
@@ -95,7 +96,7 @@ class ExpressionResolver implements ContextRewriter {
try {
if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table) && !srcAlias.equals(table)) {
cubeql.addOptionalDimTable(table, null,
- false, esc.getTblAliasToColumns().get(table).toArray(new String[0]));
+ false, null, false, esc.getTblAliasToColumns().get(table).toArray(new String[0]));
esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
}
} catch (HiveException e) {
@@ -132,7 +133,7 @@ class ExpressionResolver implements ContextRewriter {
for (String table : esc.getTblAliasToColumns().keySet()) {
try {
if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table) && !srcAlias.equals(table)) {
- cubeql.addOptionalDimTable(table, null, false,
+ cubeql.addOptionalDimTable(table, null, false, null, false,
esc.getTblAliasToColumns().get(table).toArray(new String[0]));
esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
}
@@ -171,17 +172,17 @@ class ExpressionResolver implements ContextRewriter {
if (evalSet == null) {
evalSet = new LinkedHashSet<ExprSpecContext>();
evaluableExpressions.put(cTable, evalSet);
- // add optional dimensions involved in expressions
- for (String table : esc.getTblAliasToColumns().keySet()) {
- try {
- if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table) && !srcAlias.equals(table)) {
- cubeql.addOptionalDimTable(table, cTable,
- false, esc.getTblAliasToColumns().get(table).toArray(new String[0]));
- esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
- }
- } catch (HiveException e) {
- throw new SemanticException(e);
+ }
+ // add optional dimensions involved in expressions
+ for (String table : esc.getTblAliasToColumns().keySet()) {
+ try {
+ if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table) && !srcAlias.equals(table)) {
+ cubeql.addOptionalExprDimTable(table, exprCol.getName(), srcAlias, cTable,
+ esc.getTblAliasToColumns().get(table).toArray(new String[0]));
+ esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
}
+ } catch (HiveException e) {
+ throw new SemanticException(e);
}
}
evalSet.add(esc);
@@ -210,6 +211,7 @@ class ExpressionResolver implements ContextRewriter {
private Set<ExprSpec> exprSpecs = new LinkedHashSet<ExprSpec>();
@Getter
private ASTNode finalAST;
+ @Getter
private Set<Dimension> exprDims = new HashSet<Dimension>();
// for each expression store alias to columns queried
@Getter
@@ -367,6 +369,7 @@ class ExpressionResolver implements ContextRewriter {
}
for (ExprSpecContext esc : ec.allExprs) {
if (esc.getTblAliasToColumns().get(alias) == null) {
+ log.debug("{} = {} is evaluable in {}", expr, esc, cTable);
ec.addEvaluable(cubeql, cTable, esc);
} else {
Set<String> columns = esc.getTblAliasToColumns().get(alias);
http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5f859118/lens-cube/src/main/java/org/apache/lens/cube/parse/JoinResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/JoinResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/JoinResolver.java
index a760599..97c7a46 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/JoinResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/JoinResolver.java
@@ -1016,7 +1016,7 @@ class JoinResolver implements ContextRewriter {
for (JoinChain chain : cubeql.getJoinchains().values()) {
for (String dimName : chain.getIntermediateDimensions()) {
- cubeql.addOptionalDimTable(dimName, null, true, null);
+ cubeql.addOptionalJoinDimTable(dimName, true);
}
}
@@ -1122,7 +1122,7 @@ class JoinResolver implements ContextRewriter {
for (TableRelationship rel : joinPath.getEdges()) {
// Add the joined tables to the queries table sets so that they are
// resolved in candidate resolver
- cubeql.addOptionalDimTable(rel.getToTable().getName(), null, required, null);
+ cubeql.addOptionalJoinDimTable(rel.getToTable().getName(), required);
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5f859118/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDenormalizationResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDenormalizationResolver.java b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDenormalizationResolver.java
index e615ccc..8c3c219 100644
--- a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDenormalizationResolver.java
+++ b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDenormalizationResolver.java
@@ -23,7 +23,9 @@ import static org.apache.lens.cube.parse.CubeTestSetup.*;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.apache.lens.cube.parse.CandidateTablePruneCause.CandidateTablePruneCode;
import org.apache.lens.server.api.error.LensException;
@@ -164,7 +166,7 @@ public class TestDenormalizationResolver extends TestQueryRewrite {
}))
);
put("summary1,cheapfact,testfactmonthly,testfact2,testfact",
- Arrays.asList(CandidateTablePruneCause.columnNotFound("dim2big1", "dim2")));
+ Arrays.asList(CandidateTablePruneCause.columnNotFound("dim2big2")));
}
}
));
@@ -225,6 +227,34 @@ public class TestDenormalizationResolver extends TestQueryRewrite {
}
@Test
+ public void testCubeQueryWithTwoRefCols() throws Exception {
+ Configuration tConf = new Configuration(conf);
+ tConf.set(CubeQueryConfUtil.DRIVER_SUPPORTED_STORAGES, "");
+ CubeQueryContext cubeql = rewriteCtx("select dim2, test_time_dim2 from testcube where " + TWO_DAYS_RANGE, tConf);
+ Set<String> candidateFacts = new HashSet<String>();
+ for (CandidateFact cfact : cubeql.getCandidateFacts()) {
+ candidateFacts.add(cfact.getName().toLowerCase());
+ }
+ // testfact contains test_time_dim_hour_id, but not dim2 - it should have been removed.
+ Assert.assertFalse(candidateFacts.contains("testfact"));
+ // summary2 contains dim2, but not test_time_dim2 - it should have been removed.
+ Assert.assertFalse(candidateFacts.contains("summary2"));
+ }
+
+ @Test
+ public void testDimensionQueryWithTwoRefCols() throws Exception {
+ Configuration tConf = new Configuration(conf);
+ tConf.set(CubeQueryConfUtil.DRIVER_SUPPORTED_STORAGES, "");
+ CubeQueryContext cubeql = rewriteCtx("select citydim.zipcode, citydim.statename from" + " citydim", tConf);
+ Set<String> candidateDims = new HashSet<String>();
+ for (CandidateDim cdim : cubeql.getCandidateDims().get(cubeql.getMetastoreClient().getDimension("citydim"))) {
+ candidateDims.add(cdim.getName());
+ }
+ // city_table2 contains stateid, but not zipcode - it should have been removed.
+ Assert.assertFalse(candidateDims.contains("city_table2"));
+ }
+
+ @Test
public void testDimensionQueryWithExpressionHavingDenormColumn() throws Exception {
String hqlQuery = rewrite("select citydim.name, citydim.citystate from" + " citydim", conf);
String joinExpr =