You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lens.apache.org by am...@apache.org on 2015/01/11 07:18:02 UTC

incubator-lens git commit: LENS-169 : Add distinct keyword for attribute only selection ( Sushil Mohanty via amareshwari)

Repository: incubator-lens
Updated Branches:
  refs/heads/master e2c0547d7 -> 0db992163


LENS-169 : Add distinct keyword for attribute only selection ( Sushil Mohanty via amareshwari)


Project: http://git-wip-us.apache.org/repos/asf/incubator-lens/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-lens/commit/0db99216
Tree: http://git-wip-us.apache.org/repos/asf/incubator-lens/tree/0db99216
Diff: http://git-wip-us.apache.org/repos/asf/incubator-lens/diff/0db99216

Branch: refs/heads/master
Commit: 0db992163f0e571efd96925c67f658d6eca6f494
Parents: e2c0547
Author: Amareshwari Sriramdasu <am...@inmobi.com>
Authored: Sun Jan 11 11:47:44 2015 +0530
Committer: Amareshwari Sriramdasu <am...@inmobi.com>
Committed: Sun Jan 11 11:47:44 2015 +0530

----------------------------------------------------------------------
 .../lens/cube/parse/AggregateResolver.java      | 41 +++++++++++++--
 .../lens/cube/parse/CubeQueryConfUtil.java      |  2 +
 .../apache/lens/cube/parse/GroupbyResolver.java | 32 +++---------
 .../org/apache/lens/cube/parse/HQLParser.java   | 25 +++++++--
 .../src/main/resources/olap-query-conf.xml      |  5 ++
 .../lens/cube/parse/TestAggregateResolver.java  | 54 ++++++++++++++++++--
 src/site/apt/user/olap-query-conf.apt           | 36 +++++++------
 7 files changed, 141 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/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 2d063ef..33a4a7c 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
@@ -43,12 +43,12 @@ import org.apache.lens.cube.parse.CandidateTablePruneCause.CubeTableCause;
  * if default aggregate is defined and if there isn't already an aggregate
  * function specified on the columns.
  * </p>
- * 
+ *
  * <p>
  * Expressions which already contain aggregate sub-expressions will not be
  * changed.
  * </p>
- * 
+ *
  * <p>
  * At this point it's assumed that aliases have been added to all columns.
  * </p>
@@ -66,9 +66,8 @@ class AggregateResolver implements ContextRewriter {
     }
 
     boolean nonDefaultAggregates = false;
-    boolean aggregateResolverDisabled =
-        cubeql.getHiveConf().getBoolean(CubeQueryConfUtil.DISABLE_AGGREGATE_RESOLVER,
-            CubeQueryConfUtil.DEFAULT_DISABLE_AGGREGATE_RESOLVER);
+    boolean aggregateResolverDisabled = cubeql.getHiveConf().getBoolean(CubeQueryConfUtil.DISABLE_AGGREGATE_RESOLVER,
+        CubeQueryConfUtil.DEFAULT_DISABLE_AGGREGATE_RESOLVER);
     // Check if the query contains measures
     // 1. not inside default aggregate expressions
     // 2. With no default aggregate defined
@@ -103,6 +102,18 @@ class AggregateResolver implements ContextRewriter {
     resolveClause(cubeql, cubeql.getSelectAST());
 
     resolveClause(cubeql, cubeql.getHavingAST());
+
+    Configuration distConf = cubeql.getHiveConf();
+    boolean isDimOnlyDistinctEnabled = distConf.getBoolean(CubeQueryConfUtil.ENABLE_ATTRFIELDS_ADD_DISTINCT,
+        CubeQueryConfUtil.DEFAULT_ATTR_FIELDS_ADD_DISTINCT);
+    if (isDimOnlyDistinctEnabled) {
+      // Check if any measure/aggregate columns and distinct clause used in
+      // select tree. If not, update selectAST token "SELECT" to "SELECT DISTINCT"
+      if (!hasMeasures(cubeql, cubeql.getSelectAST()) && !isDistinctClauseUsed(cubeql.getSelectAST())
+          && !HQLParser.hasAggregate(cubeql.getSelectAST())) {
+        cubeql.getSelectAST().getToken().setType(HiveParser.TOK_SELECTDI);
+      }
+    }
   }
 
   // We need to traverse the clause looking for eligible measures which can be
@@ -237,6 +248,26 @@ class AggregateResolver implements ContextRewriter {
     return false;
   }
 
+ /*
+  * Check if distinct keyword used in node
+  */
+  private boolean isDistinctClauseUsed(ASTNode node) {
+    if (node == null) {
+      return false;
+    }
+    if (node.getToken() != null) {
+      if (node.getToken().getType() == HiveParser.TOK_FUNCTIONDI
+          || node.getToken().getType() == HiveParser.TOK_SELECTDI) {
+        return true;
+      }
+    }
+    for (int i = 0; i < node.getChildCount(); i++) {
+      if (isDistinctClauseUsed((ASTNode) node.getChild(i)))
+        return true;
+    }
+    return false;
+  }
+
   private boolean hasMeasuresInDistinctClause(CubeQueryContext cubeql, ASTNode node, boolean hasDistinct) {
     if (node == null) {
       return false;

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryConfUtil.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryConfUtil.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryConfUtil.java
index 8afaf17..f5057f4 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryConfUtil.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/CubeQueryConfUtil.java
@@ -46,6 +46,8 @@ public class CubeQueryConfUtil {
   public static final String LOOK_AHEAD_PT_PARTS_PFX = "lens.cube.query.lookahead.ptparts.forinterval.";
   public static final String ENABLE_GROUP_BY_TO_SELECT = "lens.cube.query.promote.groupby.toselect";
   public static final String ENABLE_SELECT_TO_GROUPBY = "lens.cube.query.promote.select.togroupby";
+  public static final String ENABLE_ATTRFIELDS_ADD_DISTINCT = "lens.cube.query.enable.attrfields.add.distinct";
+  public static final boolean DEFAULT_ATTR_FIELDS_ADD_DISTINCT = true;
 
   public static final String REPLACE_TIMEDIM_WITH_PART_COL = "lens.cube.query.replace.timedim";
   public static final boolean DEFAULT_MULTI_TABLE_SELECT = true;

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/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 ee61aaa..2531c49 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
@@ -18,6 +18,11 @@
  */
 package org.apache.lens.cube.parse;
 
+import static org.apache.hadoop.hive.ql.parse.HiveParser.DOT;
+import static org.apache.hadoop.hive.ql.parse.HiveParser.Identifier;
+import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_GROUPBY;
+import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_TABLE_OR_COL;
+
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
@@ -29,15 +34,12 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.ql.parse.ASTNode;
-import org.apache.hadoop.hive.ql.parse.HiveParser;
 import org.apache.hadoop.hive.ql.parse.ParseException;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
 
-import static org.apache.hadoop.hive.ql.parse.HiveParser.*;
-
 /**
  * Promotes groupby to select and select to groupby.
- * 
+ *
  */
 class GroupbyResolver implements ContextRewriter {
   private static Log LOG = LogFactory.getLog(GroupbyResolver.class.getName());
@@ -219,7 +221,7 @@ class GroupbyResolver implements ContextRewriter {
 
     for (int i = 0; i < selectASTNode.getChildCount(); i++) {
       ASTNode childNode = (ASTNode) selectASTNode.getChild(i);
-      if (hasMeasure(childNode,cubeQueryCtx) || hasAggregate(childNode)) {
+      if (hasMeasure(childNode,cubeQueryCtx) || HQLParser.hasAggregate(childNode)) {
         continue;
       }
       nonMsrNonAggSelASTChildren.add(childNode);
@@ -241,7 +243,7 @@ class GroupbyResolver implements ContextRewriter {
       if (hasMeasure(child, cubeql)) {
         continue;
       }
-      if (hasAggregate(child)) {
+      if (HQLParser.hasAggregate(child)) {
         continue;
       }
       list.add(HQLParser.getString((ASTNode) node.getChild(i)));
@@ -250,24 +252,6 @@ class GroupbyResolver implements ContextRewriter {
     return list;
   }
 
-  private boolean hasAggregate(ASTNode node) {
-    int nodeType = node.getToken().getType();
-    if (nodeType == HiveParser.TOK_TABLE_OR_COL || nodeType == HiveParser.DOT) {
-      return false;
-    } else {
-      if (HQLParser.isAggregateAST(node)) {
-        return true;
-      }
-
-      for (int i = 0; i < node.getChildCount(); i++) {
-        if (hasAggregate((ASTNode) node.getChild(i))) {
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-
   boolean hasMeasure(ASTNode node, CubeQueryContext cubeql) {
     int nodeType = node.getToken().getType();
     if (nodeType == TOK_TABLE_OR_COL || nodeType == DOT) {

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/lens-cube/src/main/java/org/apache/lens/cube/parse/HQLParser.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/HQLParser.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/HQLParser.java
index 3c551c2..d31dddc 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/HQLParser.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/HQLParser.java
@@ -64,11 +64,11 @@ import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_ISNULL;
 import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_LOCAL_DIR;
 import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_ORDERBY;
 import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_SELECT;
-import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_SELEXPR;
 import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_SELECTDI;
+import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_SELEXPR;
+import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_TAB;
 import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_TABSORTCOLNAMEASC;
 import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_TABSORTCOLNAMEDESC;
-import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_TAB;
 
 import java.io.IOException;
 import java.lang.reflect.Field;
@@ -82,7 +82,6 @@ import java.util.Queue;
 import java.util.Set;
 import java.util.regex.Pattern;
 
-import com.google.common.base.Optional;
 import org.antlr.runtime.tree.Tree;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.ql.Context;
@@ -96,6 +95,8 @@ import org.apache.hadoop.hive.ql.parse.ParseException;
 import org.apache.hadoop.hive.ql.parse.ParseUtils;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
 
+import com.google.common.base.Optional;
+
 public class HQLParser {
   public static final Pattern P_WSPACE = Pattern.compile("\\s+");
 
@@ -708,6 +709,24 @@ public class HQLParser {
     return astNodeType;
   }
 
+  public static boolean hasAggregate(ASTNode node) {
+    int nodeType = node.getToken().getType();
+    if (nodeType == HiveParser.TOK_TABLE_OR_COL || nodeType == HiveParser.DOT) {
+      return false;
+    } else {
+      if (HQLParser.isAggregateAST(node)) {
+        return true;
+      }
+
+      for (int i = 0; i < node.getChildCount(); i++) {
+        if (hasAggregate((ASTNode) node.getChild(i))) {
+          return true;
+        }
+      }
+      return false;
+    }
+  }
+
   public static boolean equalsAST(ASTNode n1, ASTNode n2) {
     if (n1 == null && n2 != null) {
       return false;

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/lens-cube/src/main/resources/olap-query-conf.xml
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/resources/olap-query-conf.xml b/lens-cube/src/main/resources/olap-query-conf.xml
index 42bd210..b204078 100644
--- a/lens-cube/src/main/resources/olap-query-conf.xml
+++ b/lens-cube/src/main/resources/olap-query-conf.xml
@@ -144,4 +144,9 @@
     <description>The simple date format of how the queried partition should be put in where clause. If nothing is specified, it will use the format from org.apache.lens.cube.metadata.UpdatePeriod for each type of partition </description>
   </property>
 
+  <property>
+    <name>lens.cube.query.enable.attrfields.add.distinct</name>
+    <value>true</value>
+    <description>When the query has only attribute fields projected from cube and the flag is set to true, distinct clause will be added for the projection so that no duplicate values will be projected. If flag is set to false, projection wont be changed, result might include duplicate values.</description>
+  </property>
 </configuration>

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/lens-cube/src/test/java/org/apache/lens/cube/parse/TestAggregateResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestAggregateResolver.java b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestAggregateResolver.java
index e24e0bc..36c8134 100644
--- a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestAggregateResolver.java
+++ b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestAggregateResolver.java
@@ -26,13 +26,8 @@ import static org.apache.lens.cube.parse.CubeTestSetup.twoDaysRange;
 import static org.apache.lens.cube.parse.TestCubeRewriter.compareQueries;
 
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.ql.parse.ParseException;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
-import org.apache.lens.cube.parse.CandidateFact;
-import org.apache.lens.cube.parse.CubeQueryConfUtil;
-import org.apache.lens.cube.parse.CubeQueryContext;
-import org.apache.lens.cube.parse.CubeQueryRewriter;
 import org.testng.Assert;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
@@ -145,6 +140,55 @@ public class TestAggregateResolver extends TestQueryRewrite {
   }
 
   @Test
+  public void testDimOnlyDistinctQuery() throws SemanticException, ParseException {
+
+    conf.setBoolean(CubeQueryConfUtil.DISABLE_AGGREGATE_RESOLVER, false);
+
+    //Add distinct
+    String query1 = "SELECT testcube.cityid,testcube.zipcode,testcube.stateid from testCube where " + twoDaysRange;
+    String hQL1 = rewrite(query1,conf);
+    String expectedQL1 =
+        getExpectedQuery(cubeName, "SELECT distinct testcube.cityid, testcube.zipcode, testcube.stateid" + " from ", null,
+            null, getWhereForDailyAndHourly2days(cubeName, "C2_testfact"));
+    compareQueries(expectedQL1, hQL1);
+
+    //Don't add distinct
+    String query2 = "SELECT count (distinct testcube.cityid) from testcube where " + twoDaysRange;
+    String hQL2 = rewrite(query2, conf);
+    String expectedQL2 =
+        getExpectedQuery(cubeName, "SELECT count (distinct testcube.cityid)" + " from ", null, null,
+            getWhereForDailyAndHourly2days(cubeName, "C2_testfact"));
+    compareQueries(expectedQL2, hQL2);
+
+    //Don't add distinct
+    String query3 = "SELECT  testcube.cityid, count(distinct testcube.stateid) from testcube where " + twoDaysRange;
+    String hQL3 = rewrite(query3, conf);
+    String expectedQL3 =
+        getExpectedQuery(cubeName, "SELECT testcube.cityid, count(distinct testcube.stateid)" + " from ", null,
+            "group by testcube.cityid", getWhereForDailyAndHourly2days(cubeName, "C2_testfact"));
+    compareQueries(expectedQL3, hQL3);
+
+    //Don't add distinct
+    String query4 = "SELECT  count(testcube.stateid) from testcube where " + twoDaysRange;
+    String hQL4 = rewrite(query4, conf);
+    String expectedQL4 =
+        getExpectedQuery(cubeName, "SELECT count(testcube.stateid)" + " from ", null,
+            null, getWhereForDailyAndHourly2days(cubeName, "C2_testfact"));
+    compareQueries(expectedQL4, hQL4);
+
+    //Don't add distinct, by setting the flag false
+    conf.setBoolean(CubeQueryConfUtil.ENABLE_ATTRFIELDS_ADD_DISTINCT, false);
+    String query5 = "SELECT  testcube.stateid from testcube where " + twoDaysRange;
+    String hQL5 = rewrite(query5, conf);
+    String expectedQL5 =
+        getExpectedQuery(cubeName, "SELECT testcube.stateid" + " from ", null,
+            null, getWhereForDailyAndHourly2days(cubeName, "C2_testfact"));
+    compareQueries(expectedQL5, hQL5);
+
+
+  }
+
+  @Test
   public void testAggregateResolverOff() throws SemanticException, ParseException {
     Configuration conf2 = new Configuration(this.conf);
     conf2.setBoolean(CubeQueryConfUtil.DISABLE_AGGREGATE_RESOLVER, true);

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/0db99216/src/site/apt/user/olap-query-conf.apt
----------------------------------------------------------------------
diff --git a/src/site/apt/user/olap-query-conf.apt b/src/site/apt/user/olap-query-conf.apt
index 2b22e8a..a35c737 100644
--- a/src/site/apt/user/olap-query-conf.apt
+++ b/src/site/apt/user/olap-query-conf.apt
@@ -30,38 +30,40 @@ OLAP query configuration
 *--+--+---+--+
 |3|lens.cube.query.driver.supported.storages| |List of comma separated storage names that supported by a driver. If no value is specified, all storages are valid|
 *--+--+---+--+
-|4|lens.cube.query.enable.multi.table.select|true|Tells whether multiple tables are allowed in from clause of final HQL query|
+|4|lens.cube.query.enable.attrfields.add.distinct|true|When the query has only attribute fields projected from cube and the flag is set to true, distinct clause will be added for the projection so that no duplicate values will be projected. If flag is set to false, projection wont be changed, result might include duplicate values.|
 *--+--+---+--+
-|5|lens.cube.query.fail.if.data.partial|false|Whether to fail the query of data is partial|
+|5|lens.cube.query.enable.multi.table.select|true|Tells whether multiple tables are allowed in from clause of final HQL query|
 *--+--+---+--+
-|6|lens.cube.query.join.type|INNER|Tells what the join type is, in-case of automatic resolution of joins is enabled|
+|6|lens.cube.query.fail.if.data.partial|false|Whether to fail the query of data is partial|
 *--+--+---+--+
-|7|lens.cube.query.lookahead.ptparts.forinterval.${interval}|1|The value of number of lookahead process time partitions for interval specified. Interval can be any Update period.|
+|7|lens.cube.query.join.type|INNER|Tells what the join type is, in-case of automatic resolution of joins is enabled|
 *--+--+---+--+
-|8|lens.cube.query.max.interval| |Maximum value of the update period that the query timed dimensions can take values of. For example, if query involves month ranges, user can say query maximum interval is daily, then no monthly partitions will be picked.|
+|8|lens.cube.query.lookahead.ptparts.forinterval.${interval}|1|The value of number of lookahead process time partitions for interval specified. Interval can be any Update period.|
 *--+--+---+--+
-|9|lens.cube.query.nonexisting.partitions| |The list of comma separated non existing partitions, if query can run with partial data. The value will be set by the cube query rewriter|
+|9|lens.cube.query.max.interval| |Maximum value of the update period that the query timed dimensions can take values of. For example, if query involves month ranges, user can say query maximum interval is daily, then no monthly partitions will be picked.|
 *--+--+---+--+
-|10|lens.cube.query.partition.where.clause.format| |The simple date format of how the queried partition should be put in where clause. If nothing is specified, it will use the format from org.apache.lens.cube.metadata.UpdatePeriod for each type of partition|
+|10|lens.cube.query.nonexisting.partitions| |The list of comma separated non existing partitions, if query can run with partial data. The value will be set by the cube query rewriter|
 *--+--+---+--+
-|11|lens.cube.query.pick.lightest.fact.first|false|If set to true, lightest fact will be resolved first than resolving storages. Otherwise, storages will be resolved to check all partitions exist and then pick lightest fact among candidates|
+|11|lens.cube.query.partition.where.clause.format| |The simple date format of how the queried partition should be put in where clause. If nothing is specified, it will use the format from org.apache.lens.cube.metadata.UpdatePeriod for each type of partition|
 *--+--+---+--+
-|12|lens.cube.query.process.time.partition.column| |The column name which is a process time column. If process time column is specified, query rewriter will look ahead the partitions of other timed dimensions inside this column.|
+|12|lens.cube.query.pick.lightest.fact.first|false|If set to true, lightest fact will be resolved first than resolving storages. Otherwise, storages will be resolved to check all partitions exist and then pick lightest fact among candidates|
 *--+--+---+--+
-|13|lens.cube.query.promote.groupby.toselect|false|Tells whether to promote group by clauses to be promoted to select expressions if they are already not projected. To enable automatic promotion, this value should be true.|
+|13|lens.cube.query.process.time.partition.column| |The column name which is a process time column. If process time column is specified, query rewriter will look ahead the partitions of other timed dimensions inside this column.|
 *--+--+---+--+
-|14|lens.cube.query.promote.select.togroupby|false|Tells whether to promote select expressions which is not inside any aggregate, to be promoted to groupby clauses, if they are already not part of groupby clauses. To enable automatic promotion, this value should be true.|
+|14|lens.cube.query.promote.groupby.toselect|false|Tells whether to promote group by clauses to be promoted to select expressions if they are already not projected. To enable automatic promotion, this value should be true.|
 *--+--+---+--+
-|15|lens.cube.query.replace.timedim|true|Tells whether timedim attribute queried in the time range should be replaced with its corresponding partition column name.|
+|15|lens.cube.query.promote.select.togroupby|false|Tells whether to promote select expressions which is not inside any aggregate, to be promoted to groupby clauses, if they are already not part of groupby clauses. To enable automatic promotion, this value should be true.|
 *--+--+---+--+
-|16|lens.cube.query.time.range.writer.class|org.apache.lens.cube.parse.ORTimeRangeWriter|The timerange writer class which specifies how the resolved partitions in timeranges should be written in final query. Available writers are org.apache.lens.cube.parse.ORTimeRangeWriter and org.apache.lens.cube.parse.BetweenTimeRangeWriter|
+|16|lens.cube.query.replace.timedim|true|Tells whether timedim attribute queried in the time range should be replaced with its corresponding partition column name.|
 *--+--+---+--+
-|17|lens.cube.query.valid.${cubename}.facttables| |List of comma separated fact tables that are valid for cube. If no value is specified, all fact tables are valid|
+|17|lens.cube.query.time.range.writer.class|org.apache.lens.cube.parse.ORTimeRangeWriter|The timerange writer class which specifies how the resolved partitions in timeranges should be written in final query. Available writers are org.apache.lens.cube.parse.ORTimeRangeWriter and org.apache.lens.cube.parse.BetweenTimeRangeWriter|
 *--+--+---+--+
-|18|lens.cube.query.valid.dim.storgaetables| |List of comma separated dimension storage tables that are valid. If no value is specified, all tables are valid|
+|18|lens.cube.query.valid.${cubename}.facttables| |List of comma separated fact tables that are valid for cube. If no value is specified, all fact tables are valid|
 *--+--+---+--+
-|19|lens.cube.query.valid.fact.${facttable}.storage.${storagename}.updateperiods| |List of comma separated update periods that are valid for a fact on a storage. If no value is specified, all update periods are valid|
+|19|lens.cube.query.valid.dim.storgaetables| |List of comma separated dimension storage tables that are valid. If no value is specified, all tables are valid|
 *--+--+---+--+
-|20|lens.cube.query.valid.fact.${facttable}.storagetables| |List of comma separated storage tables that are valid for a fact. If no value is specified, all storage tables are valid|
+|20|lens.cube.query.valid.fact.${facttable}.storage.${storagename}.updateperiods| |List of comma separated update periods that are valid for a fact on a storage. If no value is specified, all update periods are valid|
+*--+--+---+--+
+|21|lens.cube.query.valid.fact.${facttable}.storagetables| |List of comma separated storage tables that are valid for a fact. If no value is specified, all storage tables are valid|
 *--+--+---+--+
 The configuration parameters and their default values