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 2016/03/29 10:48:41 UTC

lens git commit: LENS-915 : Update CLI to show streaming results on sync executions

Repository: lens
Updated Branches:
  refs/heads/master e4f26aae8 -> 79b95f0e0


LENS-915 : Update CLI to show streaming results on sync executions


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

Branch: refs/heads/master
Commit: 79b95f0e04340e6b648ee71d41308fb03ea11e16
Parents: e4f26aa
Author: Puneet Gupta <pu...@apache.org>
Authored: Tue Mar 29 14:18:21 2016 +0530
Committer: Amareshwari Sriramadasu <am...@apache.org>
Committed: Tue Mar 29 14:18:21 2016 +0530

----------------------------------------------------------------------
 .../org/apache/lens/api/query/LensQuery.java    |  56 +++--
 .../org/apache/lens/api/query/QueryHandle.java  |   2 +-
 .../org/apache/lens/api/query/QueryStatus.java  |   8 +
 .../lens/cli/commands/BaseLensCommand.java      |   7 +-
 .../cli/commands/LensConnectionCommands.java    |   5 +-
 .../lens/cli/commands/LensQueryCommands.java    |  41 ++--
 .../lens/cli/config/LensCliConfigConstants.java |  36 +++
 .../apache/lens/cli/TestLensQueryCommands.java  | 138 +++++++++++-
 .../java/org/apache/lens/client/LensClient.java |  39 +++-
 .../org/apache/lens/client/LensConnection.java  |   2 +-
 .../org/apache/lens/client/LensStatement.java   | 218 +++++++++++++------
 .../lens/client/jdbc/LensJdbcStatement.java     |   4 +-
 .../lens/client/model/ProxyLensQuery.java       | 167 ++++++++++++++
 .../src/main/resources/lens-client-default.xml  |   7 +
 .../org/apache/lens/examples/SampleQueries.java |   4 +-
 .../java/org/apache/lens/rdd/LensRDDClient.java |   2 +-
 .../server/query/QueryExecutionServiceImpl.java |   2 +-
 .../lens/server/query/TestQueryService.java     |   4 +-
 src/site/apt/user/client-config.apt             |  14 +-
 19 files changed, 619 insertions(+), 137 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-api/src/main/java/org/apache/lens/api/query/LensQuery.java
----------------------------------------------------------------------
diff --git a/lens-api/src/main/java/org/apache/lens/api/query/LensQuery.java b/lens-api/src/main/java/org/apache/lens/api/query/LensQuery.java
index e0ee761..7d079a9 100644
--- a/lens-api/src/main/java/org/apache/lens/api/query/LensQuery.java
+++ b/lens-api/src/main/java/org/apache/lens/api/query/LensQuery.java
@@ -31,7 +31,7 @@ import org.apache.lens.api.ToYAMLString;
 import lombok.*;
 
 /**
- * The Class LensQuery.
+ * This class provides all the details about the query represented by the {@link LensQuery#queryHandle}
  */
 @XmlRootElement
 /**
@@ -79,46 +79,46 @@ import lombok.*;
  * Instantiates a new lens query.
  */
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
-@EqualsAndHashCode
+@EqualsAndHashCode(of = "queryHandle", callSuper = false)
 public class LensQuery extends ToYAMLString {
 
   /**
-   * The query handle.
+   * The query handle that represents this query uniquely
    */
   @XmlElement
   @Getter
   private QueryHandle queryHandle;
 
   /**
-   * The user query.
+   * The the query submitted by the user
    */
   @XmlElement
   @Getter
   private String userQuery;
 
   /**
-   * The submitted user.
+   * The user who submitted the query.
    */
   @XmlElement
   @Getter
   private String submittedUser;
 
   /**
-   * The priority.
+   * The priority of the query.
    */
   @XmlElement
   @Getter
   private Priority priority;
 
   /**
-   * The is persistent.
+   * Is true if query's result would be persisted by server.
    */
   @XmlElement
   @Getter
   private boolean isPersistent;
 
   /**
-   * The selected driver class name.
+   * Name of the driver which executed the query (Example: hive/testDriver, jdbc/prodDriver etc)
    */
   @XmlElement
   @Getter
@@ -126,34 +126,39 @@ public class LensQuery extends ToYAMLString {
 
   /**
    * The driver query.
+   * It is the final query (derived form user query) that was submitted by the driver for execution.
    */
   @XmlElement
   @Getter
   private String driverQuery;
 
   /**
-   * The status.
+   * The status of this query.
+   * Note: {@link QueryStatus#getStatus()} method can be used to get the {@link QueryStatus.Status} enum that defines
+   * the current state of the query. Also other utility methods are available to check the status of the query like
+   * {@link QueryStatus#queued()}, {@link QueryStatus#successful()}, {@link QueryStatus#finished()},
+   * {@link QueryStatus#failed()} and {@link QueryStatus#running()}
    */
   @XmlElement
   @Getter
   private QueryStatus status;
 
   /**
-   * The result set path.
+   * The result set path for this query if the query output was persisted by the server.
    */
   @XmlElement
   @Getter
   private String resultSetPath;
 
   /**
-   * The driver op handle.
+   * The operation handle associated with the driver, if any.
    */
   @XmlElement
   @Getter
   private String driverOpHandle;
 
   /**
-   * The query conf.
+   * The query conf that was used for executing this query.
    */
   @XmlElement
   @Getter
@@ -167,60 +172,67 @@ public class LensQuery extends ToYAMLString {
   private long submissionTime;
 
   /**
-   * The launch time.
+   * The query launch time. This will be submission time + time spent by query waiting in the queue
    */
   @XmlElement
   @Getter
   private long launchTime;
 
   /**
-   * The driver start time.
+   * The query execution start time on driver. This will >= launch time.
    */
   @XmlElement
   @Getter
   private long driverStartTime;
 
   /**
-   * The driver finish time.
+   * The the query execution end time on driver.
    */
   @XmlElement
   @Getter
   private long driverFinishTime;
 
   /**
-   * The finish time.
+   * The query finish time on server. This will be driver finish time + any extra time spent by server (like
+   * formatting the result)
    */
   @XmlElement
   @Getter
   private long finishTime;
 
   /**
-   * The closed time.
+   * The the query close time when the query is purged by the server and no more operations are pending for it.
+   * Note: not supported as of now.
    */
   @XmlElement
   @Getter
   private long closedTime;
 
   /**
-   * The query name.
+   * The query name, if any.
    */
   @XmlElement
   @Getter
   private String queryName;
 
+  /**
+   * @return error code in case of query failures
+   */
   public Integer getErrorCode() {
     return (this.status != null) ? this.status.getErrorCode() : null;
   }
 
+  /**
+   * @return error message in case of query failures
+   */
   public String getErrorMessage() {
     return (this.status != null) ? this.status.getLensErrorTOErrorMsg() : null;
   }
 
+  /**
+   * @return the query handle string
+   */
   public String getQueryHandleString() {
     return (this.queryHandle != null) ? this.queryHandle.getHandleIdString() : null;
   }
-
-  public boolean queued() {
-    return this.status.queued();
-  }
 }

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-api/src/main/java/org/apache/lens/api/query/QueryHandle.java
----------------------------------------------------------------------
diff --git a/lens-api/src/main/java/org/apache/lens/api/query/QueryHandle.java b/lens-api/src/main/java/org/apache/lens/api/query/QueryHandle.java
index 88e4b0f..81ca0e8 100644
--- a/lens-api/src/main/java/org/apache/lens/api/query/QueryHandle.java
+++ b/lens-api/src/main/java/org/apache/lens/api/query/QueryHandle.java
@@ -54,7 +54,7 @@ import lombok.*;
  *
  * @see java.lang.Object#hashCode()
  */
-@EqualsAndHashCode(callSuper = false)
+@EqualsAndHashCode(of = "handleId", callSuper = false)
 public class QueryHandle extends QuerySubmitResult implements Serializable {
 
   /**

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-api/src/main/java/org/apache/lens/api/query/QueryStatus.java
----------------------------------------------------------------------
diff --git a/lens-api/src/main/java/org/apache/lens/api/query/QueryStatus.java b/lens-api/src/main/java/org/apache/lens/api/query/QueryStatus.java
index 7a9ada1..67d1e79 100644
--- a/lens-api/src/main/java/org/apache/lens/api/query/QueryStatus.java
+++ b/lens-api/src/main/java/org/apache/lens/api/query/QueryStatus.java
@@ -81,26 +81,33 @@ public class QueryStatus extends ToYAMLString implements Serializable {
 
     /**
      * The queued.
+     * At this point the query is queued by the server and it waiting to be launched. The launch may be controlled by
+     * multiple factors like query throttling, quota, etc
      */
     QUEUED,
 
     /**
      * The launched.
+     * At this point the query is launched for execution.
      */
     LAUNCHED,
 
     /**
      * The running.
+     * At this point the query starts running on chosen driver
      */
     RUNNING,
 
     /**
      * The executed.
+     * At this point execution is finished by driver, but server may still have some more operations pending
+     * like result persistence, if enabled.
      */
     EXECUTED,
 
     /**
      * The successful.
+     * At this point all operations related to the query are finished successfully by driver and server.
      */
     SUCCESSFUL,
 
@@ -116,6 +123,7 @@ public class QueryStatus extends ToYAMLString implements Serializable {
 
     /**
      * The closed.
+     * At this point the query is purged by the server. Persistent result will still be available to the user
      */
     CLOSED
   }

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-cli/src/main/java/org/apache/lens/cli/commands/BaseLensCommand.java
----------------------------------------------------------------------
diff --git a/lens-cli/src/main/java/org/apache/lens/cli/commands/BaseLensCommand.java b/lens-cli/src/main/java/org/apache/lens/cli/commands/BaseLensCommand.java
index be1ca12..9eb73b3 100644
--- a/lens-cli/src/main/java/org/apache/lens/cli/commands/BaseLensCommand.java
+++ b/lens-cli/src/main/java/org/apache/lens/cli/commands/BaseLensCommand.java
@@ -26,6 +26,7 @@ import java.util.Date;
 
 import org.apache.lens.api.ToXMLString;
 import org.apache.lens.api.util.PathValidator;
+import org.apache.lens.cli.config.LensCliConfigConstants;
 import org.apache.lens.client.LensClient;
 import org.apache.lens.client.LensClientSingletonWrapper;
 
@@ -40,6 +41,7 @@ import org.springframework.shell.core.ExecutionProcessor;
 import org.springframework.shell.event.ParseResult;
 
 import com.google.common.collect.Sets;
+
 import lombok.extern.slf4j.Slf4j;
 
 /**
@@ -47,8 +49,6 @@ import lombok.extern.slf4j.Slf4j;
  */
 @Slf4j
 public class BaseLensCommand implements ExecutionProcessor {
-  public static final String LENS_CLI_PREFIX = "lens.cli.";
-  public static final String JSON_PRETTY_SUFFIX = "json.pretty";
 
   /** The mapper. */
   protected ObjectMapper mapper;
@@ -149,7 +149,8 @@ public class BaseLensCommand implements ExecutionProcessor {
       String json = mapper.writer(pp).writeValueAsString(data);
       JsonNode tree = mapper.valueToTree(data);
       System.out.println(tree);
-      if (getClient().getConf().getBoolean(LENS_CLI_PREFIX + JSON_PRETTY_SUFFIX, false)) {
+      if (getClient().getConf().getBoolean(LensCliConfigConstants.PRINT_PRETTY_JSON,
+          LensCliConfigConstants.DEFAULT_PRINT_PRETTY_JSON)) {
         return json;
       }
       return json.replaceAll("\\[ \\{", "\n\n ").replaceAll("\\{", "").replaceAll("}", "").replaceAll("\\[", "")

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-cli/src/main/java/org/apache/lens/cli/commands/LensConnectionCommands.java
----------------------------------------------------------------------
diff --git a/lens-cli/src/main/java/org/apache/lens/cli/commands/LensConnectionCommands.java b/lens-cli/src/main/java/org/apache/lens/cli/commands/LensConnectionCommands.java
index b760dad..e548cac 100644
--- a/lens-cli/src/main/java/org/apache/lens/cli/commands/LensConnectionCommands.java
+++ b/lens-cli/src/main/java/org/apache/lens/cli/commands/LensConnectionCommands.java
@@ -26,6 +26,7 @@ import javax.ws.rs.ProcessingException;
 import org.apache.lens.api.APIResult;
 import org.apache.lens.api.LensSessionHandle;
 import org.apache.lens.cli.commands.annotations.UserDocumentation;
+import org.apache.lens.cli.config.LensCliConfigConstants;
 import org.apache.lens.client.LensClient;
 import org.apache.lens.client.LensClientConfig;
 
@@ -43,7 +44,9 @@ import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.ConsoleAppender;
 import ch.qos.logback.core.Context;
+
 import com.google.common.base.Joiner;
+
 import lombok.NonNull;
 import lombok.extern.slf4j.Slf4j;
 
@@ -70,7 +73,7 @@ public class LensConnectionCommands extends BaseLensCommand {
     if (pair.length != 2) {
       return "Error: Pass parameter as <key>=<value>";
     }
-    if (pair[0].startsWith(LENS_CLI_PREFIX) || pair[0].startsWith(LensClientConfig.CLIENT_PFX)) {
+    if (pair[0].startsWith(LensCliConfigConstants.LENS_CLI_PREFIX) || pair[0].startsWith(LensClientConfig.CLIENT_PFX)) {
       getClient().getConf().set(pair[0], pair[1]);
       return "Client side Set " + pair[0] + "=" + pair[1];
     } else {

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-cli/src/main/java/org/apache/lens/cli/commands/LensQueryCommands.java
----------------------------------------------------------------------
diff --git a/lens-cli/src/main/java/org/apache/lens/cli/commands/LensQueryCommands.java b/lens-cli/src/main/java/org/apache/lens/cli/commands/LensQueryCommands.java
index 2c7b17f..af05951 100644
--- a/lens-cli/src/main/java/org/apache/lens/cli/commands/LensQueryCommands.java
+++ b/lens-cli/src/main/java/org/apache/lens/cli/commands/LensQueryCommands.java
@@ -28,7 +28,10 @@ import javax.ws.rs.core.Response;
 import org.apache.lens.api.query.*;
 import org.apache.lens.api.result.PrettyPrintable;
 import org.apache.lens.cli.commands.annotations.UserDocumentation;
+import org.apache.lens.cli.config.LensCliConfigConstants;
 import org.apache.lens.client.LensClient;
+import org.apache.lens.client.LensClient.LensClientResultSetWithStats;
+import org.apache.lens.client.LensClientResultSet;
 import org.apache.lens.client.exceptions.LensAPIException;
 import org.apache.lens.client.exceptions.LensBriefErrorException;
 import org.apache.lens.client.model.BriefError;
@@ -107,16 +110,28 @@ public class LensQueryCommands extends BaseLensCommand {
 
     try {
       if (async) {
-        QueryHandle queryHandle = getClient().executeQueryAsynch(sql, queryName).getData();
+        QueryHandle queryHandle = getClient().executeQueryAsynch(sql, queryName);
         return queryHandle.getHandleIdString();
       } else {
-        return formatResultSet(getClient().getResults(sql, queryName));
+        LensClientResultSetWithStats resultWithStats;
+        long timeOutMillis = getClient().getConf().getLong(LensCliConfigConstants.QUERY_EXECUTE_TIMEOUT_MILLIS,
+            LensCliConfigConstants.DEFAULT_QUERY_EXECUTE_TIMEOUT_MILLIS);
+        LensClient.getCliLogger().info("Executing query with timeout of {} milliseconds", timeOutMillis);
+        QueryHandleWithResultSet result = getClient().executeQueryWithTimeout(sql, queryName, timeOutMillis);
+        if (result.getResult() == null) {
+          //Query not finished yet. Wait till it finishes and get result.
+          LensClient.getCliLogger().info("Couldn't complete query execution within timeout. Waiting for completion");
+          resultWithStats = getClient().getSyncResults(result.getQueryHandle());
+        } else {
+          LensClientResultSet clientResultSet = new LensClientResultSet(result.getResultMetadata(), result.getResult());
+          resultWithStats =
+              new LensClientResultSetWithStats(clientResultSet, getClient().getQueryDetails(result.getQueryHandle()));
+        }
+        return formatResultSet(resultWithStats);
       }
     } catch (final LensAPIException e) {
-
       BriefError briefError = new BriefError(e.getLensAPIErrorCode(), e.getLensAPIErrorMessage());
       cliOutput = new IdBriefErrorTemplate(IdBriefErrorTemplateKey.REQUEST_ID, e.getLensAPIRequestId(), briefError);
-
     } catch (final LensBriefErrorException e) {
       cliOutput = e.getIdBriefErrorTemplate();
     }
@@ -436,17 +451,17 @@ public class LensQueryCommands extends BaseLensCommand {
     @CliOption(key = {"async"}, mandatory = false, unspecifiedDefaultValue = "false",
       specifiedDefaultValue = "true", help = "<async>") boolean async,
     @CliOption(key = {"name"}, mandatory = false, help = "<query-name>") String queryName) {
-    if (async) {
-      QueryHandle handle = getClient().executePrepared(QueryPrepareHandle.fromString(phandle), queryName);
-      return handle.getHandleId().toString();
-    } else {
-      try {
-        LensClient.LensClientResultSetWithStats result = getClient().getResultsFromPrepared(
-          QueryPrepareHandle.fromString(phandle), queryName);
+    try {
+      if (async) {
+        QueryHandle handle = getClient().executePrepared(QueryPrepareHandle.fromString(phandle), queryName);
+        return handle.getHandleId().toString();
+      } else {
+        LensClient.LensClientResultSetWithStats result =
+            getClient().getResultsFromPrepared(QueryPrepareHandle.fromString(phandle), queryName);
         return formatResultSet(result);
-      } catch (Throwable t) {
-        return t.getMessage();
       }
+    } catch (Throwable t) {
+      return t.getMessage();
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-cli/src/main/java/org/apache/lens/cli/config/LensCliConfigConstants.java
----------------------------------------------------------------------
diff --git a/lens-cli/src/main/java/org/apache/lens/cli/config/LensCliConfigConstants.java b/lens-cli/src/main/java/org/apache/lens/cli/config/LensCliConfigConstants.java
new file mode 100644
index 0000000..5651c31
--- /dev/null
+++ b/lens-cli/src/main/java/org/apache/lens/cli/config/LensCliConfigConstants.java
@@ -0,0 +1,36 @@
+/**
+ * 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.cli.config;
+
+public class LensCliConfigConstants {
+
+  private LensCliConfigConstants(){
+  }
+
+  public static final String LENS_CLI_PREFIX = "lens.cli.";
+
+  public static final String PRINT_PRETTY_JSON = LENS_CLI_PREFIX + "json.pretty";
+
+  public static final boolean DEFAULT_PRINT_PRETTY_JSON = false;
+
+  public static final String QUERY_EXECUTE_TIMEOUT_MILLIS = LENS_CLI_PREFIX  + "query.execute.timeout.millis";
+
+  public static final long DEFAULT_QUERY_EXECUTE_TIMEOUT_MILLIS = 10000; //10 secs
+}

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-cli/src/test/java/org/apache/lens/cli/TestLensQueryCommands.java
----------------------------------------------------------------------
diff --git a/lens-cli/src/test/java/org/apache/lens/cli/TestLensQueryCommands.java b/lens-cli/src/test/java/org/apache/lens/cli/TestLensQueryCommands.java
index 616bf5d..dbb5e9d 100644
--- a/lens-cli/src/test/java/org/apache/lens/cli/TestLensQueryCommands.java
+++ b/lens-cli/src/test/java/org/apache/lens/cli/TestLensQueryCommands.java
@@ -23,6 +23,8 @@ import static org.testng.Assert.*;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.util.*;
 
@@ -31,17 +33,23 @@ import javax.xml.datatype.DatatypeFactory;
 
 import org.apache.lens.api.APIResult;
 import org.apache.lens.api.metastore.*;
+import org.apache.lens.api.query.LensQuery;
 import org.apache.lens.api.query.QueryHandle;
 import org.apache.lens.api.query.QueryStatus;
 import org.apache.lens.cli.commands.LensCubeCommands;
 import org.apache.lens.cli.commands.LensDimensionTableCommands;
 import org.apache.lens.cli.commands.LensQueryCommands;
+import org.apache.lens.cli.config.LensCliConfigConstants;
 import org.apache.lens.client.LensClient;
+import org.apache.lens.client.model.ProxyLensQuery;
 import org.apache.lens.driver.hive.TestHiveDriver;
+import org.apache.lens.server.api.LensConfConstants;
+import org.apache.lens.server.query.TestQueryService.DeferredInMemoryResultFormatter;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.fs.Path;
 
+import org.testng.Assert;
 import org.testng.annotations.*;
 
 import lombok.extern.slf4j.Slf4j;
@@ -92,6 +100,46 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
     return qCom;
   }
 
+  @DataProvider(name = "executeSyncQueryDP")
+  private Object[][] executeSyncQueryDP() {
+    //Streaming not enabled. InMemory ResultSet Expected
+    LensClient client1 = new LensClient();
+    client1.setConnectionParam("lens.query.enable.persistent.resultset.indriver", "false");
+    client1.setConnectionParam("lens.query.enable.persistent.resultset", "false");
+    client1.setConnectionParam("lens.query.enable.metrics.per.query", "true");
+    client1.getConf().setLong(LensCliConfigConstants.QUERY_EXECUTE_TIMEOUT_MILLIS, 100);
+    LensQueryCommands qCom1 = new LensQueryCommands();
+    qCom1.setClient(client1);
+
+    //Streaming case. Query execution and formatting finishes fast.
+    //InMemory result set Excepted.
+    LensClient client2 = new LensClient();
+    client2.setConnectionParam("lens.query.enable.persistent.resultset.indriver", "false");
+    client2.setConnectionParam("lens.query.enable.persistent.resultset", "true");
+    client2.getConf().setLong(LensCliConfigConstants.QUERY_EXECUTE_TIMEOUT_MILLIS, 20000);
+    LensQueryCommands qCom2 = new LensQueryCommands();
+    qCom2.setClient(client2);
+
+    //Streaming case. Query execution finishes fast, but server takes long time to format result.
+    //InMemory ResultSet Excepted.
+    //Wait for query to be successful (i,e finish both execution and formatting)
+    LensClient client3 = new LensClient();
+    client3.setConnectionParam("lens.query.enable.persistent.resultset.indriver", "false");
+    client3.setConnectionParam("lens.query.enable.persistent.resultset", "true");
+    client3.setConnectionParam(LensConfConstants.QUERY_OUTPUT_FORMATTER,
+        DeferredInMemoryResultFormatter.class.getName());
+    client3.setConnectionParam("deferPersistenceByMillis", "5000"); // property used for test only
+    client3.getConf().setLong(LensCliConfigConstants.QUERY_EXECUTE_TIMEOUT_MILLIS, 20000);
+    LensQueryCommands qCom3 = new LensQueryCommands();
+    qCom3.setClient(client3);
+
+    return new Object[][] {
+      { qCom1, "cube select id,name from test_dim", true, false },
+      { qCom1, "cube select id,name1 from invalid_test_dim", false, true }, // this query should fail;
+      { qCom2, "cube select id,name from test_dim", true, true },
+      { qCom3, "cube select id,name from test_dim", true, true }, };
+  }
+
   private void closeClientConnection(LensQueryCommands queryCommands) {
     queryCommands.getClient().closeConnection();
   }
@@ -99,13 +147,43 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
   /**
    * Test execute sync query
    */
-  @Test(dataProvider = "queryCommands")
-  public void executeSyncQuery(LensQueryCommands qCom) {
+  @Test(dataProvider = "executeSyncQueryDP")
+  public void executeSyncQuery(LensQueryCommands qCom, String sql, boolean shouldPass, boolean closeConn)
+    throws Exception{
     assertEquals(qCom.getAllPreparedQueries("all", "", -1, -1), "No prepared queries");
-    String sql = "cube select id,name from test_dim";
-    String result = qCom.executeQuery(sql, false, "testQuery2");
-    assertTrue(result.contains("1\tfirst"), result);
-    closeClientConnection(qCom);
+    String successfulQueries = qCom.getAllQueries("SUCCESSFUL", null, "all", null, -1, Long.MAX_VALUE);
+    int noOfSuccQueriesSoFar;
+    if (successfulQueries.contains("No queries")) {
+      noOfSuccQueriesSoFar = 0;
+    } else {
+      noOfSuccQueriesSoFar = Integer.parseInt(successfulQueries.substring(successfulQueries.lastIndexOf(": ") + 2));
+    }
+    try {
+      String result = qCom.executeQuery(sql, false, "testQuerySync");
+      assertTrue(result.contains("1\tfirst"), result);
+    } catch (Exception e) {
+      if (closeConn) {
+        closeClientConnection(qCom);
+      }
+      if (shouldPass) {
+        fail("Unexpected failure", e);
+      } else {
+        return; //simulated failure scenario
+      }
+    }
+    // Wait for query to reach successful state
+    int chkCount = 0;
+    while (!qCom.getAllQueries("SUCCESSFUL", null, "all", null, -1, Long.MAX_VALUE).contains(
+        "Total number of queries: " + (noOfSuccQueriesSoFar + 1))) {
+      Thread.sleep(2000);
+      chkCount++;
+      if (chkCount > 30) {
+        fail("Unable to get successful status for query even after 30 checks");
+      }
+    }
+    if (closeConn) {
+      closeClientConnection(qCom);
+    }
   }
 
   /**
@@ -152,7 +230,7 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
     //Fetch again. Should not get resultset
     result = qCom.getQueryResults(handle, null, true);
     log.debug("Prepared Query Result is  " + result);
-    assertTrue(result.contains("Resultset not available for the query"), "Query is not purged yet " + handle);
+    assertTrue(result.contains("Failed"), "Query is not purged yet " + handle);
 
     result = qCom.destroyPreparedQuery(qh);
 
@@ -171,6 +249,7 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
     assertFalse(handles2.contains(qh), handles2);
     result = qCom.destroyPreparedQuery(handles);
     assertEquals("Successfully destroyed " + handles, result);
+
     closeClientConnection(qCom);
   }
 
@@ -204,6 +283,7 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
 
     log.debug(result);
     assertTrue(result.contains(explainPlan));
+
     closeClientConnection(qCom);
   }
 
@@ -223,6 +303,8 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
 
     result = qCom.explainAndPrepare(sql, "");
     assertTrue(result.contains("Explain FAILED:"));
+
+    closeClientConnection(qCom);
   }
 
   /**
@@ -401,6 +483,7 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
     downloadResult(qCom, qCom.getClient().getStatement().getQueryHandleString(), "testQuery3",  "\"1\",\"first\"");
     System.out.println("@@END_PERSISTENT_RESULT_TEST-------------");
     qCom.getClient().setConnectionParam("lens.query.enable.persistent.resultset.indriver", "false");
+
     closeClientConnection(qCom);
   }
 
@@ -450,7 +533,48 @@ public class TestLensQueryCommands extends LensCliApplicationTest {
     assertFalse(result.contains("(-"));
     System.out.println("@@END_FINISHED_PURGED_RESULT_TEST-------------");
     qCom.getClient().setConnectionParam("lens.query.enable.persistent.resultset", "false");
+
     closeClientConnection(qCom);
   }
 
+  @Test
+  public void testProxyLensQuery() throws Exception {
+    LensClient client = new LensClient();
+    QueryHandle handle = client.executeQueryAsynch("cube select id,name from test_dim", "proxyTestQuery");
+    client.getStatement().waitForQueryToComplete(handle);
+    LensQuery query = client.getQueryDetails(handle);
+    ProxyLensQuery proxyQuery = new ProxyLensQuery(client.getStatement(), handle);
+    Assert.assertEquals(query.getStatus().successful(), proxyQuery.getStatus().successful());
+    Assert.assertEquals(query.getSubmissionTime(), proxyQuery.getSubmissionTime());
+    Assert.assertEquals(query.getFinishTime(), proxyQuery.getFinishTime());
+
+    //Check is any new getters are added to LensQuery. If yes, ProxyLensQuery should be updated too
+    Set<String> lensQueryMethods = new HashSet<String>();
+    for (Method m :query.getClass().getDeclaredMethods()) {
+      if (Modifier.isPublic(m.getModifiers()) && !m.getName().startsWith("hash") && !m.getName().startsWith("equals")) {
+        lensQueryMethods.add(m.getName());
+      }
+    }
+
+    Set<String> proxyLensQueryMethods = new HashSet<String>();
+    for (Method m :proxyQuery.getClass().getDeclaredMethods()) {
+      if (Modifier.isPublic(m.getModifiers())) {
+        proxyLensQueryMethods.add(m.getName());
+      }
+    }
+
+    log.info("Methods in LensQuery: " + lensQueryMethods + "\nMethods in ProxyLensQuery: " + proxyLensQueryMethods);
+    assertTrue(lensQueryMethods.containsAll(proxyLensQueryMethods),
+        "Methods in LensQuery and ProxyLensQuery do not match");
+
+
+    //Check equals and hashCode override
+    ProxyLensQuery proxyQuery2 = new ProxyLensQuery(client.getStatement(), handle);
+    Assert.assertEquals(proxyQuery, proxyQuery2);
+    Assert.assertEquals(proxyQuery, query);
+    Assert.assertEquals(proxyQuery.hashCode(), proxyQuery2.hashCode());
+    Assert.assertEquals(proxyQuery.hashCode(), query.hashCode());
+
+    client.closeConnection();
+  }
 }

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-client/src/main/java/org/apache/lens/client/LensClient.java
----------------------------------------------------------------------
diff --git a/lens-client/src/main/java/org/apache/lens/client/LensClient.java b/lens-client/src/main/java/org/apache/lens/client/LensClient.java
index 39d771c..9626820 100644
--- a/lens-client/src/main/java/org/apache/lens/client/LensClient.java
+++ b/lens-client/src/main/java/org/apache/lens/client/LensClient.java
@@ -64,7 +64,7 @@ public class LensClient {
   @Getter
   private PathValidator pathValidator;
 
-  public static Logger getCliLooger() {
+  public static Logger getCliLogger() {
     return LoggerFactory.getLogger(CLILOGGER);
   }
 
@@ -100,13 +100,36 @@ public class LensClient {
     return mc;
   }
 
-  public LensAPIResult<QueryHandle> executeQueryAsynch(String sql, String queryName) throws LensAPIException {
+  public QueryHandle executeQueryAsynch(String sql, String queryName) throws LensAPIException {
     log.debug("Executing query {}", sql);
-    LensAPIResult<QueryHandle> lensAPIResult = statement.execute(sql, false, queryName);
-    LensQuery query = statement.getQuery();
-    log.debug("Adding query to statementMap {}", query.getQueryHandle());
-    statementMap.put(query.getQueryHandle(), statement);
-    return lensAPIResult;
+    QueryHandle handle = statement.executeQuery(sql, false, queryName);
+    statementMap.put(handle, statement);
+    return handle;
+  }
+
+  /**
+   * Execute query with timeout option.
+   * If the query does not finish within the timeout time, server returns the query handle which can be used to
+   * track further progress.
+   *
+   * @param sql : query/command to be executed
+   * @param queryName : optional query name
+   * @param timeOutMillis : timeout milliseconds for the query execution.
+   * @return
+   * @throws LensAPIException
+   */
+  public QueryHandleWithResultSet executeQueryWithTimeout(String sql, String queryName, long timeOutMillis)
+    throws LensAPIException {
+    log.info("Executing query {} with timeout of {} milliseconds", sql, timeOutMillis);
+    QueryHandleWithResultSet result = statement.executeQuery(sql, queryName, timeOutMillis);
+    statementMap.put(result.getQueryHandle(), statement);
+    if (result.getStatus().failed()) {
+      IdBriefErrorTemplate errorResult = new IdBriefErrorTemplate(IdBriefErrorTemplateKey.QUERY_ID,
+          result.getQueryHandle().getHandleIdString(), new BriefError(result.getStatus()
+              .getErrorCode(), result.getStatus().getErrorMessage()));
+      throw new LensBriefErrorException(errorResult);
+    }
+    return result;
   }
 
   public Date getLatestDateOfCube(String cubeName, String timePartition) {
@@ -139,7 +162,7 @@ public class LensClient {
 
   public LensClientResultSetWithStats getResults(String sql, String queryName) throws LensAPIException {
     log.debug("Executing query {}", sql);
-    statement.execute(sql, true, queryName);
+    statement.executeQuery(sql, true, queryName);
     return getResultsFromStatement(statement);
   }
 

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-client/src/main/java/org/apache/lens/client/LensConnection.java
----------------------------------------------------------------------
diff --git a/lens-client/src/main/java/org/apache/lens/client/LensConnection.java b/lens-client/src/main/java/org/apache/lens/client/LensConnection.java
index eeb473a..d67e64e 100644
--- a/lens-client/src/main/java/org/apache/lens/client/LensConnection.java
+++ b/lens-client/src/main/java/org/apache/lens/client/LensConnection.java
@@ -311,7 +311,7 @@ public class LensConnection {
     return value.getElements();
   }
 
-  LensConnectionParams getLensConnectionParams() {
+  public LensConnectionParams getLensConnectionParams() {
     return this.params;
   }
 

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-client/src/main/java/org/apache/lens/client/LensStatement.java
----------------------------------------------------------------------
diff --git a/lens-client/src/main/java/org/apache/lens/client/LensStatement.java b/lens-client/src/main/java/org/apache/lens/client/LensStatement.java
index 33c26e1..f06bcd1 100644
--- a/lens-client/src/main/java/org/apache/lens/client/LensStatement.java
+++ b/lens-client/src/main/java/org/apache/lens/client/LensStatement.java
@@ -31,9 +31,9 @@ import org.apache.lens.api.APIResult;
 import org.apache.lens.api.LensConf;
 import org.apache.lens.api.query.*;
 import org.apache.lens.api.query.QueryStatus.Status;
-
 import org.apache.lens.api.result.LensAPIResult;
 import org.apache.lens.client.exceptions.LensAPIException;
+import org.apache.lens.client.model.ProxyLensQuery;
 
 import org.apache.commons.lang.StringUtils;
 
@@ -58,59 +58,42 @@ public class LensStatement {
   private LensQuery query;
 
   /**
-   * Execute.
-   *
-   * @param sql                    the sql
-   * @param waitForQueryToComplete the wait for query to complete
-   * @param queryName              the query name
-   */
-  public LensAPIResult<QueryHandle> execute(String sql, boolean waitForQueryToComplete,
-      String queryName) throws LensAPIException {
-    LensAPIResult<QueryHandle> lensAPIResult = executeQuery(sql, waitForQueryToComplete, queryName);
-    this.query = getQuery(lensAPIResult.getData());
-    return lensAPIResult;
-  }
-
-  /**
-   * Execute.
-   *
-   * @param sql       the sql
-   * @param queryName the query name
-   */
-  public void execute(String sql, String queryName) throws LensAPIException {
-    QueryHandle handle = executeQuery(sql, true, queryName).getData();
-    this.query = getQuery(handle);
-  }
-
-  /**
-   * Execute query.
+   * This method can be used for executing a query. If waitForQueryToComplete is false, the call to this method returns
+   * immediately after submitting the query to the server without waiting for it to complete execution.
+   * <p>
+   * {@link #getStatus(QueryHandle)} can be used to track to track the query progress and
+   * {@link #getQuery(QueryHandle)} can be used to get complete details (including status) about the query.
    *
    * @param sql                    the sql
    * @param waitForQueryToComplete the wait for query to complete
    * @param queryName              the query name
    * @return the query handle
    */
-  public LensAPIResult<QueryHandle> executeQuery(String sql, boolean waitForQueryToComplete,
-      String queryName) throws LensAPIException {
+  public QueryHandle executeQuery(String sql, boolean waitForQueryToComplete, String queryName)
+    throws LensAPIException {
 
-    LensAPIResult<QueryHandle> lensAPIResult = executeQuery(sql, queryName);
+    QueryHandle handle = submitQuery(sql, queryName);
 
     if (waitForQueryToComplete) {
-      waitForQueryToComplete(lensAPIResult.getData());
+      waitForQueryToComplete(handle);
     }
-    return lensAPIResult;
+    return handle;
   }
 
   /**
-   * Execute query.
+   * This method can be used for executing a prepared query. If waitForQueryToComplete is false, the call to this method
+   * returns immediately after submitting the query to the server without waiting for it to complete execution.
+   * <p>
+   * {@link #getStatus(QueryHandle)} can be used to track to track the query progress and
+   * {@link #getQuery(QueryHandle)} can be used to get complete details (including status) about the query.
    *
-   * @param phandle                the phandle
+   * @param phandle                the prepared query handle
    * @param waitForQueryToComplete the wait for query to complete
    * @param queryName              the query name
    * @return the query handle
    */
   public QueryHandle executeQuery(QueryPrepareHandle phandle, boolean waitForQueryToComplete, String queryName) {
-    QueryHandle handle = executeQuery(phandle, queryName);
+    QueryHandle handle = submitQuery(phandle, queryName);
 
     if (waitForQueryToComplete) {
       waitForQueryToComplete(handle);
@@ -119,6 +102,57 @@ public class LensStatement {
   }
 
   /**
+   * This method can be used for executing query. The method waits for timeOutMillis time OR query execution to succeed,
+   * which ever happens first, before returning the response to the caller.
+   * <p>
+   * If the query execution finishes before timeout, user can check the query Status (SUCCESSFUL/FAILED) using
+   * {@link QueryHandleWithResultSet#getStatus()} and access the result of SUCCESSFUL query via
+   * {@link QueryHandleWithResultSet#getResult()} and {@link QueryHandleWithResultSet#getResultMetadata()}.
+   * <p>
+   * If the query does not finish within the timeout, user can use {@link #getStatus(QueryHandle)} to track
+   * the query progress and {@link #getQuery(QueryHandle)} to get complete details (including status) about
+   * the query. Once the query has reached SUCCESSFUL state, user can access the results via
+   * {@link #getResultSet(LensQuery)} and {@link #getResultSetMetaData(LensQuery)}
+   *
+   * @param sql : query/command to be executed
+   * @param queryName : optional query name
+   * @param timeOutMillis : timeout milliseconds
+   * @return QueryHandleWithResultSet
+   * @throws LensAPIException
+   */
+  public QueryHandleWithResultSet executeQuery(String sql, String queryName, long timeOutMillis)
+    throws LensAPIException {
+    if (!connection.isOpen()) {
+      throw new IllegalStateException("Lens Connection has to be established before querying");
+    }
+
+    Client client = connection.buildClient();
+    FormDataMultiPart mp = new FormDataMultiPart();
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("sessionid").build(), connection
+        .getSessionHandle(), MediaType.APPLICATION_XML_TYPE));
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("query").build(), sql));
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("operation").build(), "EXECUTE_WITH_TIMEOUT"));
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("timeoutmillis").build(), "" + timeOutMillis));
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("queryName").build(), queryName == null ? ""
+        : queryName));
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("conf").fileName("conf").build(), new LensConf(),
+        MediaType.APPLICATION_XML_TYPE));
+    WebTarget target = getQueryWebTarget(client);
+
+    Response response =
+        target.request(MediaType.APPLICATION_XML_TYPE).post(Entity.entity(mp, MediaType.MULTIPART_FORM_DATA_TYPE));
+
+    if (response.getStatus() == Response.Status.OK.getStatusCode()) {
+      QueryHandleWithResultSet result =
+          response.readEntity(new GenericType<LensAPIResult<QueryHandleWithResultSet>>() {}).getData();
+      this.query = new ProxyLensQuery(this, result.getQueryHandle());
+      return result;
+    }
+
+    throw new LensAPIException(response.readEntity(LensAPIResult.class));
+  }
+
+  /**
    * Prepare query.
    *
    * @param sql       the sql
@@ -200,27 +234,27 @@ public class LensStatement {
    * @param handle the handle
    */
   public void waitForQueryToComplete(QueryHandle handle) {
-    LensClient.getCliLooger().info("Query handle: {}", handle);
-    query = getQuery(handle);
-    while (query.queued()) {
-      query = getQuery(handle);
-      LensClient.getCliLooger().debug("Query {} status: {}", handle, query.getStatus());
+    LensClient.getCliLogger().info("Query handle: {}", handle);
+    LensQuery queryDetails = getQuery(handle);
+    while (queryDetails.getStatus().queued()) {
+      queryDetails = getQuery(handle);
+      LensClient.getCliLogger().debug("Query {} status: {}", handle, queryDetails.getStatus());
       try {
         Thread.sleep(connection.getLensConnectionParams().getQueryPollInterval());
       } catch (InterruptedException e) {
         throw new IllegalStateException(e);
       }
     }
-    LensClient.getCliLooger().info("User query: '{}' was submitted to {}", query.getUserQuery(),
-      query.getSelectedDriverName());
-    if (query.getDriverQuery() != null) {
-      LensClient.getCliLooger().info(" Driver query: '{}' and Driver handle: {}", query.getDriverQuery(),
-        query.getDriverOpHandle());
+    LensClient.getCliLogger().info("User query: '{}' was submitted to {}", queryDetails.getUserQuery(),
+      queryDetails.getSelectedDriverName());
+    if (queryDetails.getDriverQuery() != null) {
+      LensClient.getCliLogger().info(" Driver query: '{}' and Driver handle: {}", queryDetails.getDriverQuery(),
+        queryDetails.getDriverOpHandle());
     }
-    while (!query.getStatus().finished()
-      && !(query.getStatus().getStatus().equals(Status.CLOSED))) {
-      query = getQuery(handle);
-      LensClient.getCliLooger().info("Query Status:{} ", query.getStatus());
+    while (!queryDetails.getStatus().finished()
+      && !(queryDetails.getStatus().getStatus().equals(Status.CLOSED))) {
+      queryDetails = getQuery(handle);
+      LensClient.getCliLogger().info("Query Status:{} ", queryDetails.getStatus());
       try {
         Thread.sleep(connection.getLensConnectionParams().getQueryPollInterval());
       } catch (InterruptedException e) {
@@ -261,9 +295,8 @@ public class LensStatement {
     try {
       Client client = connection.buildClient();
       WebTarget target = getQueryWebTarget(client);
-      this.query = target.path(handle.toString()).queryParam("sessionid", connection.getSessionHandle()).request()
+      return target.path(handle.toString()).queryParam("sessionid", connection.getSessionHandle()).request()
         .get(LensQuery.class);
-      return query;
     } catch (Exception e) {
       log.error("Failed to get query status, cause:", e);
       throw new IllegalStateException("Failed to get query status, cause:" + e.getMessage());
@@ -295,7 +328,7 @@ public class LensStatement {
    * @param queryName the query name
    * @return the query handle
    */
-  private LensAPIResult<QueryHandle> executeQuery(String sql, String queryName) throws LensAPIException {
+  private QueryHandle submitQuery(String sql, String queryName) throws LensAPIException {
     if (!connection.isOpen()) {
       throw new IllegalStateException("Lens Connection has to be established before querying");
     }
@@ -305,7 +338,7 @@ public class LensStatement {
     mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("sessionid").build(), connection
       .getSessionHandle(), MediaType.APPLICATION_XML_TYPE));
     mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("query").build(), sql));
-    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("operation").build(), "execute"));
+    mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("operation").build(), "EXECUTE"));
     mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("queryName").build(), queryName == null ? ""
       : queryName));
     mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("conf").fileName("conf").build(), new LensConf(),
@@ -315,7 +348,9 @@ public class LensStatement {
     Response response = target.request().post(Entity.entity(mp, MediaType.MULTIPART_FORM_DATA_TYPE));
 
     if (response.getStatus() == Response.Status.OK.getStatusCode()) {
-      return response.readEntity(new GenericType<LensAPIResult<QueryHandle>>() {});
+      QueryHandle handle = response.readEntity(new GenericType<LensAPIResult<QueryHandle>>() {}).getData();
+      this.query = new ProxyLensQuery(this, handle);
+      return handle;
     }
 
     throw new LensAPIException(response.readEntity(LensAPIResult.class));
@@ -327,8 +362,9 @@ public class LensStatement {
    * @param phandle   the phandle
    * @param queryName the query name
    * @return the query handle
+   * @throws LensAPIException
    */
-  public QueryHandle executeQuery(QueryPrepareHandle phandle, String queryName) {
+  private QueryHandle submitQuery(QueryPrepareHandle phandle, String queryName) {
     if (!connection.isOpen()) {
       throw new IllegalStateException("Lens Connection has to be " + "established before querying");
     }
@@ -344,8 +380,9 @@ public class LensStatement {
     mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("conf").fileName("conf").build(), new LensConf(),
       MediaType.APPLICATION_XML_TYPE));
     QueryHandle handle = target.request()
-      .post(Entity.entity(mp, MediaType.MULTIPART_FORM_DATA_TYPE), QueryHandle.class);
+        .post(Entity.entity(mp, MediaType.MULTIPART_FORM_DATA_TYPE), QueryHandle.class);
 
+    this.query = new ProxyLensQuery(this, handle);
     return handle;
   }
 
@@ -420,8 +457,11 @@ public class LensStatement {
     return handles;
   }
 
+  /**
+   * Gets the result set meta data for the most recently executed query.
+   */
   public QueryResultSetMetadata getResultSetMetaData() {
-    return this.getResultSetMetaData(query);
+    return this.getResultSetMetaData(this.getQuery());
   }
 
   /**
@@ -447,12 +487,18 @@ public class LensStatement {
     }
   }
 
+  /**
+   * Gets result set for the most recently executed query.
+   */
   public QueryResult getResultSet() {
-    return this.getResultSet(this.query);
+    return this.getResultSet(this.getQuery());
   }
 
+  /**
+   * Gets http result set for the most recently executed query.
+   */
   public Response getHttpResultSet() {
-    return this.getHttpResultSet(this.query);
+    return this.getHttpResultSet(this.getQuery());
   }
 
   /**
@@ -501,12 +547,12 @@ public class LensStatement {
   }
 
   /**
-   * Kill.
+   * Kill the most recently submitted query via any executeQuery methods.
    *
    * @return true, if successful
    */
   public boolean kill() {
-    return this.kill(query);
+    return this.kill(this.getQuery());
   }
 
   /**
@@ -536,7 +582,7 @@ public class LensStatement {
    * @return true, if successful
    */
   public boolean closeResultSet() {
-    if (!query.getStatus().isResultSetAvailable()) {
+    if (!this.getQuery().getStatus().isResultSetAvailable()) {
       return false;
     }
     Client client = connection.buildClient();
@@ -565,35 +611,73 @@ public class LensStatement {
   }
 
   public boolean isIdle() {
-    return query == null || query.getStatus().finished();
+    return query == null || this.getQuery().getStatus().finished();
   }
 
   /**
-   * Was query successful.
+   * Was the most recently executed query successful.
    *
    * @return true, if successful
    */
   public boolean wasQuerySuccessful() {
-    return query.getStatus().getStatus().equals(QueryStatus.Status.SUCCESSFUL);
+    return this.getQuery().getStatus().getStatus().equals(QueryStatus.Status.SUCCESSFUL);
+  }
+
+  /**
+   * Gets status for query represented by handle.
+   */
+  public QueryStatus getStatus(QueryHandle handle) {
+    return getQuery(handle).getStatus();
   }
 
+  /**
+   * Gets the status for the most recently executed query.
+   */
   public QueryStatus getStatus() {
     return getQuery().getStatus();
   }
 
+  /**
+   * Gets details of the most recently executed query through {@link #executeQuery(QueryPrepareHandle, boolean, String)}
+   * or {@link #executeQuery(String, boolean, String)} or {@link #executeQuery(String, String, long)}
+   * <p>
+   * Note: Cached query details are returned if the query has finished. If the query has still not finished it fetches
+   * the latest details from server again.
+   */
   public LensQuery getQuery() {
+    if (this.query != null && !this.query.getStatus().finished()) {
+      // Get Updated Query if the query has not finished yet.
+      this.query = getQuery(this.query.getQueryHandle());
+    }
     return this.query;
   }
 
+  /**
+   *Gets the error code, if any, for the most recently executed query.
+   */
   public int getErrorCode() {
-    return this.query.getErrorCode();
+    return this.getQuery().getErrorCode();
   }
 
+  /**
+   * Gets the error message, if any, for the most recently executed query.
+   */
   public String getErrorMessage() {
-    return this.query.getErrorMessage();
+    return this.getQuery().getErrorMessage();
   }
 
+  /**
+   * Gets the query handle string for the most recently executed query.
+   */
   public String getQueryHandleString() {
     return this.query.getQueryHandleString();
   }
+
+  /**
+   * Gets the user for the lens session
+   */
+  public String getUser() {
+    return this.connection.getLensConnectionParams().getUser();
+  }
 }
+

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-client/src/main/java/org/apache/lens/client/jdbc/LensJdbcStatement.java
----------------------------------------------------------------------
diff --git a/lens-client/src/main/java/org/apache/lens/client/jdbc/LensJdbcStatement.java b/lens-client/src/main/java/org/apache/lens/client/jdbc/LensJdbcStatement.java
index 10f7155..fb265e5 100644
--- a/lens-client/src/main/java/org/apache/lens/client/jdbc/LensJdbcStatement.java
+++ b/lens-client/src/main/java/org/apache/lens/client/jdbc/LensJdbcStatement.java
@@ -58,7 +58,7 @@ public class LensJdbcStatement implements Statement {
   @Override
   public ResultSet executeQuery(String s) throws SQLException {
     try {
-      statement.execute(s, null);
+      statement.executeQuery(s, true, null);
     } catch (LensAPIException e) {
       log.error("Execution Failed for Statement:{}", s, e);
     }
@@ -115,7 +115,7 @@ public class LensJdbcStatement implements Statement {
       throw new SQLException("Cannot execute statemes on closed statements");
     }
     try {
-      statement.execute(s, true, null);
+      statement.executeQuery(s, true, null);
     } catch (Throwable t) {
       throw new SQLException(t);
     }

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-client/src/main/java/org/apache/lens/client/model/ProxyLensQuery.java
----------------------------------------------------------------------
diff --git a/lens-client/src/main/java/org/apache/lens/client/model/ProxyLensQuery.java b/lens-client/src/main/java/org/apache/lens/client/model/ProxyLensQuery.java
new file mode 100644
index 0000000..e8b3488
--- /dev/null
+++ b/lens-client/src/main/java/org/apache/lens/client/model/ProxyLensQuery.java
@@ -0,0 +1,167 @@
+/**
+ * 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.client.model;
+
+import org.apache.lens.api.LensConf;
+import org.apache.lens.api.Priority;
+import org.apache.lens.api.query.LensQuery;
+import org.apache.lens.api.query.QueryHandle;
+import org.apache.lens.api.query.QueryStatus;
+import org.apache.lens.client.LensStatement;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * This class can be used to create Proxy Lens Query objects. The Proxy objects support lazy initialization
+ * of members of this class given a query handle and LensStatement.
+ * <p>
+ * In most cases the query handle information should suffice which is available locally, and only in a few cases
+ * like {@link org.apache.lens.client.LensClient.LensClientResultSetWithStats}, extra information needs to be fetched
+ * from Lens Server.
+ * <p>
+ * Note:This class if not meant to be instantiated by lens apps (using lens-client to interact with lens server)
+ * directly
+ */
+@Slf4j
+public class ProxyLensQuery extends LensQuery {
+
+  private LensStatement statement;
+  private QueryHandle queryHandle;
+  private boolean isFullyInitialized;
+  private LensQuery actualLensQuery;
+
+  public ProxyLensQuery(LensStatement statement, QueryHandle queryHandle) {
+    this.statement = statement;
+    this.queryHandle = queryHandle;
+  }
+
+  @Override
+  public QueryHandle getQueryHandle() {
+    return this.queryHandle;
+  }
+
+  @Override
+  public String getSubmittedUser() {
+    return this.statement.getUser();
+  }
+
+  @Override
+  public String getUserQuery() {
+    return getQuery().getUserQuery();
+  }
+
+  @Override
+  public Priority getPriority() {
+    return getQuery().getPriority();
+  }
+
+  @Override
+  public boolean isPersistent() {
+    return getQuery().isPersistent();
+  }
+
+  @Override
+  public String getSelectedDriverName() {
+    return getQuery().getSelectedDriverName();
+  }
+
+  @Override
+  public String getDriverQuery() {
+    return getQuery().getDriverQuery();
+  }
+
+  @Override
+  public QueryStatus getStatus() {
+    return getQuery().getStatus();
+  }
+
+  @Override
+  public String getResultSetPath() {
+    return getQuery().getResultSetPath();
+  }
+
+  @Override
+  public String getDriverOpHandle() {
+    return getQuery().getDriverOpHandle();
+  }
+
+  @Override
+  public LensConf getQueryConf() {
+    return getQuery().getQueryConf();
+  }
+
+  @Override
+  public long getSubmissionTime() {
+    return getQuery().getSubmissionTime();
+  }
+
+  @Override
+  public long getLaunchTime() {
+    return getQuery().getLaunchTime();
+  }
+
+  @Override
+  public long getDriverStartTime() {
+    return getQuery().getDriverStartTime();
+  }
+
+  @Override
+  public long getDriverFinishTime() {
+    return getQuery().getDriverFinishTime();
+  }
+
+  @Override
+  public long getFinishTime() {
+    return getQuery().getFinishTime();
+  }
+
+  @Override
+  public long getClosedTime() {
+    return getQuery().getClosedTime();
+  }
+
+  @Override
+  public String getQueryName() {
+    return getQuery().getQueryName();
+  }
+
+  @Override
+  public Integer getErrorCode() {
+    return getQuery().getErrorCode();
+  }
+
+  @Override
+  public String getErrorMessage() {
+    return getQuery().getErrorMessage();
+  }
+
+  @Override
+  public String getQueryHandleString() {
+    return getQuery().getQueryHandleString();
+  }
+
+  private synchronized LensQuery getQuery() {
+    if (!isFullyInitialized) {
+      this.actualLensQuery = statement.getQuery(queryHandle);
+      this.isFullyInitialized = true;
+    }
+    return actualLensQuery;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-client/src/main/resources/lens-client-default.xml
----------------------------------------------------------------------
diff --git a/lens-client/src/main/resources/lens-client-default.xml b/lens-client/src/main/resources/lens-client-default.xml
index 35b2d28..5a578a7 100644
--- a/lens-client/src/main/resources/lens-client-default.xml
+++ b/lens-client/src/main/resources/lens-client-default.xml
@@ -56,4 +56,11 @@
     <value>false</value>
     <description>Should CLI try to prettify the JSON of an object before priting.</description>
   </property>
+  <property>
+    <name>lens.cli.query.execute.timeout.millis</name>
+    <value>10000</value>
+    <description>This property defines the timeout value when sync or --async false option
+    is used to execute a query. The default value is 10 seconds.
+    </description>
+  </property>
 </configuration>

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-examples/src/main/java/org/apache/lens/examples/SampleQueries.java
----------------------------------------------------------------------
diff --git a/lens-examples/src/main/java/org/apache/lens/examples/SampleQueries.java b/lens-examples/src/main/java/org/apache/lens/examples/SampleQueries.java
index 805a282..e88ed28 100644
--- a/lens-examples/src/main/java/org/apache/lens/examples/SampleQueries.java
+++ b/lens-examples/src/main/java/org/apache/lens/examples/SampleQueries.java
@@ -134,7 +134,7 @@ public class SampleQueries {
       total++;
       System.out.println("Query:" + query);
       try {
-        QueryHandle handle = queryClient.executeQuery(query, true, null).getData();
+        QueryHandle handle = queryClient.executeQuery(query, true, null);
         System.out.println("Status:" + queryClient.getQuery().getStatus());
         System.out.println("Total time in millis:"
           + (queryClient.getQuery().getFinishTime() - queryClient.getQuery().getSubmissionTime()));
@@ -160,7 +160,7 @@ public class SampleQueries {
           retCode = 1;
         }
       } catch (Exception e) {
-        LensClient.getCliLooger().error("Exception for example query : \"{}\"", query, e);
+        LensClient.getCliLogger().error("Exception for example query : \"{}\"", query, e);
         retCode = 1;
       }
       System.out.println("--------------------");

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-ml-lib/src/main/java/org/apache/lens/rdd/LensRDDClient.java
----------------------------------------------------------------------
diff --git a/lens-ml-lib/src/main/java/org/apache/lens/rdd/LensRDDClient.java b/lens-ml-lib/src/main/java/org/apache/lens/rdd/LensRDDClient.java
index b4f43ec..860b219 100644
--- a/lens-ml-lib/src/main/java/org/apache/lens/rdd/LensRDDClient.java
+++ b/lens-ml-lib/src/main/java/org/apache/lens/rdd/LensRDDClient.java
@@ -164,7 +164,7 @@ public class LensRDDClient {
    * @throws LensAPIException the lens exception
    */
   public QueryHandle createLensRDDAsync(String query) throws LensAPIException {
-    return getClient().executeQueryAsynch(query, "").getData();
+    return getClient().executeQueryAsynch(query, "");
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-server/src/main/java/org/apache/lens/server/query/QueryExecutionServiceImpl.java
----------------------------------------------------------------------
diff --git a/lens-server/src/main/java/org/apache/lens/server/query/QueryExecutionServiceImpl.java b/lens-server/src/main/java/org/apache/lens/server/query/QueryExecutionServiceImpl.java
index 581530f..47efb1c 100644
--- a/lens-server/src/main/java/org/apache/lens/server/query/QueryExecutionServiceImpl.java
+++ b/lens-server/src/main/java/org/apache/lens/server/query/QueryExecutionServiceImpl.java
@@ -540,7 +540,7 @@ public class QueryExecutionServiceImpl extends BaseLensService implements QueryE
           driverRS = ctx.getSelectedDriver().fetchResultSet(getCtx());
         } catch (Exception e) {
           log.error(
-              "Error while getting result ser form driver {}. Driver result set based purging logic will be ignored",
+              "Error while getting result set form driver {}. Driver result set based purging logic will be ignored",
               ctx.getSelectedDriver(), e);
         }
       }

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/lens-server/src/test/java/org/apache/lens/server/query/TestQueryService.java
----------------------------------------------------------------------
diff --git a/lens-server/src/test/java/org/apache/lens/server/query/TestQueryService.java b/lens-server/src/test/java/org/apache/lens/server/query/TestQueryService.java
index 49de59c..df13ba2 100644
--- a/lens-server/src/test/java/org/apache/lens/server/query/TestQueryService.java
+++ b/lens-server/src/test/java/org/apache/lens/server/query/TestQueryService.java
@@ -1359,7 +1359,7 @@ public class TestQueryService extends LensJerseyTest {
         false, true, MediaType.APPLICATION_XML_TYPE);
   }
 
-  private static class DeferredInMemoryResultFormatter extends FileSerdeFormatter {
+  public static class DeferredInMemoryResultFormatter extends FileSerdeFormatter {
     /**
      * Defer init so that this output formatter takes significant time.
      */
@@ -1370,7 +1370,7 @@ public class TestQueryService extends LensJerseyTest {
     }
   }
 
-  private static class DeferredPersistentResultFormatter extends FilePersistentFormatter {
+  public static class DeferredPersistentResultFormatter extends FilePersistentFormatter {
     /**
      * Defer init so that this output formatter takes significant time.
      */

http://git-wip-us.apache.org/repos/asf/lens/blob/79b95f0e/src/site/apt/user/client-config.apt
----------------------------------------------------------------------
diff --git a/src/site/apt/user/client-config.apt b/src/site/apt/user/client-config.apt
index 714db18..4ed41b4 100644
--- a/src/site/apt/user/client-config.apt
+++ b/src/site/apt/user/client-config.apt
@@ -26,16 +26,18 @@ Lens client configuration
 *--+--+---+--+
 |1|lens.cli.json.pretty|false|Should CLI try to prettify the JSON of an object before priting.|
 *--+--+---+--+
-|2|lens.client.dbname|default|Default lens database|
+|2|lens.cli.query.execute.timeout.millis|10000|This property defines the timeout value when sync or --async false option is used to execute a query. The default value is 10 seconds.|
 *--+--+---+--+
-|3|lens.client.query.poll.interval|10|Interval at which query progress will be polled. Interval has to be given in milliseconds|
+|3|lens.client.dbname|default|Default lens database|
 *--+--+---+--+
-|4|lens.client.requestfilter.ws.filter.impl|org.apache.lens.client.RequestFilter|Implementation class for Request Filter|
+|4|lens.client.query.poll.interval|10000|Interval at which query progress will be polled. Interval has to be given in milliseconds|
 *--+--+---+--+
-|5|lens.client.user.name|anonymous|Lens client user name|
+|5|lens.client.requestfilter.ws.filter.impl|org.apache.lens.client.RequestFilter|Implementation class for Request Filter|
 *--+--+---+--+
-|6|lens.client.ws.request.filternames|requestfilter|These JAX-RS filters would be started in the specified order when lens-client starts|
+|6|lens.client.user.name|anonymous|Lens client user name|
 *--+--+---+--+
-|7|lens.server.base.url|http://0.0.0.0:9999/lensapi|The base url for the lens server|
+|7|lens.client.ws.request.filternames|requestfilter|These JAX-RS filters would be started in the specified order when lens-client starts|
+*--+--+---+--+
+|8|lens.server.base.url|http://0.0.0.0:9999/lensapi|The base url for the lens server|
 *--+--+---+--+
 The configuration parameters and their default values