This is an automated email from the ASF dual-hosted git repository.

arina pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/drill.git

commit 82e1a1229203efc3f8899c620a7efc60dff6d388
Author: Kunal Khatua <ku...@apache.org>
AuthorDate: Wed May 16 10:35:51 2018 -0700

    DRILL-6423: Export query result as a CSV file
    
    Added option for user specified delimiter
    Also, we show query Id on results page as alink for popping out a new window
    
    closes #1266
---
 .../drill/exec/server/rest/QueryResources.java     |  6 ++
 .../drill/exec/server/rest/QueryWrapper.java       | 12 +++-
 .../src/main/resources/rest/query/result.ftl       | 71 +++++++++++++++++++++-
 3 files changed, 85 insertions(+), 4 deletions(-)

diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryResources.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryResources.java
index c46c4b5..e69b261 100644
--- 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryResources.java
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryResources.java
@@ -96,8 +96,10 @@ public class QueryResources {
   public static class TabularResult {
     private final List<String> columns;
     private final List<List<String>> rows;
+    private final String queryId;
 
     public TabularResult(QueryResult result) {
+      queryId = result.getQueryId();
       final List<List<String>> rows = Lists.newArrayList();
       for (Map<String, String> rowMap:result.rows) {
         final List<String> row = Lists.newArrayList();
@@ -115,6 +117,10 @@ public class QueryResources {
       return columns.isEmpty();
     }
 
+    public String getQueryId() {
+      return queryId;
+    }
+
     public List<String> getColumns() {
       return columns;
     }
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryWrapper.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryWrapper.java
index 6a92942..911ac0f 100644
--- 
a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryWrapper.java
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/QueryWrapper.java
@@ -23,6 +23,7 @@ import com.google.common.collect.Maps;
 import org.apache.drill.exec.proto.UserBitShared.QueryId;
 import org.apache.drill.exec.proto.UserBitShared.QueryType;
 import org.apache.drill.exec.proto.UserProtos.RunQuery;
+import org.apache.drill.exec.proto.helper.QueryIdHelper;
 import org.apache.drill.exec.proto.UserProtos.QueryResultsMode;
 import org.apache.drill.exec.work.WorkManager;
 
@@ -79,18 +80,23 @@ public class QueryWrapper {
     }
 
     // Return the QueryResult.
-    return new QueryResult(webUserConnection.columns, 
webUserConnection.results);
+    return new QueryResult(queryId, webUserConnection.columns, 
webUserConnection.results);
   }
 
   public static class QueryResult {
+    private final String queryId;
     public final Collection<String> columns;
-
     public final List<Map<String, String>> rows;
 
-    public QueryResult(Collection<String> columns, List<Map<String, String>> 
rows) {
+    public QueryResult(QueryId queryId, Collection<String> columns, 
List<Map<String, String>> rows) {
+      this.queryId = QueryIdHelper.getQueryId(queryId);
       this.columns = columns;
       this.rows = rows;
     }
+
+    public String getQueryId() {
+      return queryId;
+    }
   }
 
   @Override
diff --git a/exec/java-exec/src/main/resources/rest/query/result.ftl 
b/exec/java-exec/src/main/resources/rest/query/result.ftl
index 37eeca8..96e68b0 100644
--- a/exec/java-exec/src/main/resources/rest/query/result.ftl
+++ b/exec/java-exec/src/main/resources/rest/query/result.ftl
@@ -30,6 +30,22 @@
   <a href="/queries">back</a><br/>
   <div class="page-header">
   </div>
+  <div>
+  <table><tr>
+    <td align='left'>
+      <button type="button"  title="Open in new window" 
onclick="popOutProfile('${model.getQueryId()}');" class="btn btn-default 
btn-sm">
+      <b>Query Profile:</b> ${model.getQueryId()} <span class="glyphicon 
glyphicon-new-window"/></button>
+     </td><td align="right" width="100%">
+       <div class="input-group">
+         <span class="input-group-addon" style="font-size:95%">Delimiter 
</span>
+         <input id="delimitBy" type="text" class="form-control input-sm" 
name="delimitBy" title="Specify delimiter" placeholder="Required" maxlength="2" 
size="2" value=",">
+       </div></td><td>
+       <button type="button"  title="Export visible table as CSV. Show ALL 
rows to export entire resultSet" 
onclick="exportTableAsCsv('${model.getQueryId()}');" class="btn btn-default 
btn-sm">
+       <b>Export </b> <span class="glyphicon glyphicon-export"/></button>
+     </td>
+  </tr>
+  </table>
+  </div>
   <#if model.isEmpty()>
     <div class="jumbotron">
       <p class="lead">No result found.</p>
@@ -59,11 +75,64 @@
       $('#result').dataTable( {
         "aaSorting": [],
         "scrollX" : true,
+        "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
+        "lengthChange": true,
         "dom": '<"H"lCfr>t<"F"ip>',
         "jQueryUI" : true
       } );
     } );
-  </script>
+
+    //Pop out profile (needed to avoid losing query results)
+    function popOutProfile(queryId) {
+      var profileUrl = location.protocol+'//'+ 
location.host+'/profiles/'+queryId;
+      var tgtWindow = '_blank';
+      window.open(profileUrl, tgtWindow);
+    }
+
+    //Ref: https://jsfiddle.net/gengns/j1jm2tjx/
+    function downloadCsv(csvRecords, filename) {
+      var csvFile;
+      var downloadElem;
+
+      //CSV File
+      csvFile = new Blob([csvRecords], {type: "text/csv"});
+      // Download link
+      downloadElem = document.createElement("a");
+      // File name
+      downloadElem.download = filename;
+
+      // We have to create a link to the file
+      downloadElem.href = window.URL.createObjectURL(csvFile);
+
+      // Make sure that the link is not displayed
+      downloadElem.style.display = "none";
+
+      // Add the link to your DOM
+      document.body.appendChild(downloadElem);
+
+      // Launch the download prompt
+      downloadElem.click();
+    }
+
+    function exportTableAsCsv(queryId) {
+      var filename = queryId + '.csv';
+      var csv = []; //Array of records
+      var rows = document.getElementById('result').querySelectorAll("tr");
+      var delimiter = document.getElementById('delimitBy').value;
+      if (delimiter == 'undefined' || delimiter.length==0) {
+        delimiter = ",";
+      }
+      for (var i = 0; i < rows.length; i++) {
+        var row = [], cols = rows[i].querySelectorAll("th, td");
+        for (var j = 0; j < cols.length; j++)
+          row.push(cols[j].textContent);
+          csv.push(row.join(delimiter));
+        }
+        // Download CSV
+        downloadCsv(csv.join("\n"), filename);
+    }
+
+    </script>
 </#macro>
 
 <@page_html/>

-- 
To stop receiving notification emails like this one, please contact
ar...@apache.org.

Reply via email to