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

xiangfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 132009c  Make sql as default query format. (#4994)
132009c is described below

commit 132009c311eb72908fe1d25a7218b1b737bda9ef
Author: Xiang Fu <[email protected]>
AuthorDate: Fri Jan 24 18:28:16 2020 -0800

    Make sql as default query format. (#4994)
    
    * Make sql as default query format.
    
    * Update TransformExpressionTree.java
    
    * Adding sql endpoint in controller
    
    * Address comments
    
    * move sql back to pql parser
    
    * move sql parser to calcite parser again
---
 ...lQueryResource.java => PinotQueryResource.java} | 149 ++++++++++++++++-----
 .../src/main/resources/static/js/init.js           | 110 ++++++++-------
 .../src/main/resources/static/query/index.html     |   7 +-
 .../src/main/resources/webapp/index.html           |   7 +-
 .../src/main/resources/webapp/js/init.js           |  39 +++---
 5 files changed, 195 insertions(+), 117 deletions(-)

diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PqlQueryResource.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
similarity index 60%
rename from 
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PqlQueryResource.java
rename to 
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
index abacf9b..eadec54 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PqlQueryResource.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -45,30 +46,33 @@ import org.apache.pinot.common.Utils;
 import org.apache.pinot.common.config.TableNameBuilder;
 import org.apache.pinot.common.exception.QueryException;
 import org.apache.pinot.common.request.BrokerRequest;
-import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.common.utils.CommonConstants;
 import org.apache.pinot.controller.api.access.AccessControl;
 import org.apache.pinot.controller.api.access.AccessControlFactory;
 import org.apache.pinot.controller.helix.core.PinotHelixResourceManager;
 import org.apache.pinot.pql.parsers.Pql2Compiler;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.sql.parsers.CalciteSqlCompiler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 @Path("/")
-public class PqlQueryResource {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(PqlQueryResource.class);
-  private static final Pql2Compiler REQUEST_COMPILER = new Pql2Compiler();
+public class PinotQueryResource {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(PinotQueryResource.class);
+  private static final Pql2Compiler PQL_QUERY_COMPILER = new Pql2Compiler();
+  private static final CalciteSqlCompiler SQL_QUERY_COMPILER = new 
CalciteSqlCompiler();
   private static final Random RANDOM = new Random();
-
   @Inject
   PinotHelixResourceManager _pinotHelixResourceManager;
 
   @Inject
   AccessControlFactory _accessControlFactory;
 
+  @Deprecated
   @POST
   @Path("pql")
-  public String post(String requestJsonStr, @Context HttpHeaders httpHeaders) {
+  public String handlePostPql(String requestJsonStr, @Context HttpHeaders 
httpHeaders) {
     try {
       JsonNode requestJson = JsonUtils.stringToJsonNode(requestJsonStr);
       String pqlQuery = requestJson.get("pql").asText();
@@ -81,37 +85,88 @@ public class PqlQueryResource {
         queryOptions = requestJson.get("queryOptions").asText();
       }
       LOGGER.debug("Trace: {}, Running query: {}", traceEnabled, pqlQuery);
-      return getQueryResponse(pqlQuery, traceEnabled, queryOptions, 
httpHeaders);
+      return getQueryResponse(pqlQuery, traceEnabled, queryOptions, 
httpHeaders, CommonConstants.Broker.Request.PQL);
     } catch (Exception e) {
       LOGGER.error("Caught exception while processing post request", e);
       return QueryException.getException(QueryException.INTERNAL_ERROR, 
e).toString();
     }
   }
 
+  @Deprecated
   @GET
   @Path("pql")
-  public String get(@QueryParam("pql") String pqlQuery, @QueryParam("trace") 
String traceEnabled,
-      @QueryParam("queryOptions") String queryOptions,
-      @Context HttpHeaders httpHeaders) {
+  public String handleGetPql(@QueryParam("pql") String pqlQuery, 
@QueryParam("trace") String traceEnabled,
+      @QueryParam("queryOptions") String queryOptions, @Context HttpHeaders 
httpHeaders) {
     try {
       LOGGER.debug("Trace: {}, Running query: {}", traceEnabled, pqlQuery);
-      return getQueryResponse(pqlQuery, traceEnabled, queryOptions, 
httpHeaders);
+      return getQueryResponse(pqlQuery, traceEnabled, queryOptions, 
httpHeaders, CommonConstants.Broker.Request.PQL);
+    } catch (Exception e) {
+      LOGGER.error("Caught exception while processing get request", e);
+      return QueryException.getException(QueryException.INTERNAL_ERROR, 
e).toString();
+    }
+  }
+
+  /**
+   * Current handlePostSql method internally still use pql compiler to parse 
query.
+   *
+   * @param requestJsonStr
+   * @param httpHeaders
+   * @return
+   */
+  @POST
+  @Path("sql")
+  public String handlePostSql(String requestJsonStr, @Context HttpHeaders 
httpHeaders) {
+    try {
+      JsonNode requestJson = JsonUtils.stringToJsonNode(requestJsonStr);
+      String sqlQuery = requestJson.get("sql").asText();
+      String traceEnabled = "false";
+      if (requestJson.has("trace")) {
+        traceEnabled = requestJson.get("trace").toString();
+      }
+      String queryOptions = null;
+      if (requestJson.has("queryOptions")) {
+        queryOptions = requestJson.get("queryOptions").asText();
+      }
+      LOGGER.debug("Trace: {}, Running query: {}", traceEnabled, sqlQuery);
+      return getQueryResponse(sqlQuery, traceEnabled, queryOptions, 
httpHeaders, CommonConstants.Broker.Request.SQL);
+    } catch (Exception e) {
+      LOGGER.error("Caught exception while processing post request", e);
+      return QueryException.getException(QueryException.INTERNAL_ERROR, 
e).toString();
+    }
+  }
+
+  @GET
+  @Path("sql")
+  public String handleGetSql(@QueryParam("sql") String sqlQuery, 
@QueryParam("trace") String traceEnabled,
+      @QueryParam("queryOptions") String queryOptions, @Context HttpHeaders 
httpHeaders) {
+    try {
+      LOGGER.debug("Trace: {}, Running query: {}", traceEnabled, sqlQuery);
+      return getQueryResponse(sqlQuery, traceEnabled, queryOptions, 
httpHeaders, CommonConstants.Broker.Request.SQL);
     } catch (Exception e) {
       LOGGER.error("Caught exception while processing get request", e);
       return QueryException.getException(QueryException.INTERNAL_ERROR, 
e).toString();
     }
   }
 
-  public String getQueryResponse(String pqlQuery, String traceEnabled, String 
queryOptions,
-      HttpHeaders httpHeaders) {
+  public String getQueryResponse(String query, String traceEnabled, String 
queryOptions, HttpHeaders httpHeaders,
+      String querySyntax) {
     // Get resource table name.
     BrokerRequest brokerRequest;
     try {
-      brokerRequest = REQUEST_COMPILER.compileToBrokerRequest(pqlQuery);
+      switch (querySyntax) {
+        case CommonConstants.Broker.Request.SQL:
+          brokerRequest = SQL_QUERY_COMPILER.compileToBrokerRequest(query);
+          break;
+        case CommonConstants.Broker.Request.PQL:
+          brokerRequest = PQL_QUERY_COMPILER.compileToBrokerRequest(query);
+          break;
+        default:
+          throw new UnsupportedOperationException("Unsupported query syntax - 
" + querySyntax);
+      }
       String inputTableName = brokerRequest.getQuerySource().getTableName();
       
brokerRequest.getQuerySource().setTableName(_pinotHelixResourceManager.getActualTableName(inputTableName));
     } catch (Exception e) {
-      LOGGER.info("Caught exception while compiling PQL query: {}, {}", 
pqlQuery, e.getMessage());
+      LOGGER.error("Caught exception while compiling {} query: {}", 
querySyntax.toUpperCase(), query, e);
       return QueryException.getException(QueryException.PQL_PARSING_ERROR, 
e).toString();
     }
     String tableName = 
TableNameBuilder.extractRawTableName(brokerRequest.getQuerySource().getTableName());
@@ -143,9 +198,43 @@ public class PqlQueryResource {
     }
     String hostNameWithPrefix = instanceConfig.getHostName();
     String url =
-        "http://"; + 
hostNameWithPrefix.substring(hostNameWithPrefix.indexOf("_") + 1) + ":" + 
instanceConfig.getPort()
-            + "/query";
-    return sendPQLRaw(url, pqlQuery, traceEnabled, queryOptions);
+        
getQueryURL(hostNameWithPrefix.substring(hostNameWithPrefix.indexOf("_") + 1), 
instanceConfig.getPort(),
+            querySyntax);
+    ObjectNode requestJson = getRequestJson(query, traceEnabled, queryOptions, 
querySyntax);
+    return sendRequestRaw(url, query, requestJson);
+  }
+
+  private ObjectNode getRequestJson(String query, String traceEnabled, String 
queryOptions, String querySyntax) {
+    // Currently the request is still processed by PQL parser.
+    ObjectNode requestJson = JsonUtils.newObjectNode();
+    switch (querySyntax) {
+      case CommonConstants.Broker.Request.SQL:
+        requestJson.put("sql", query);
+        break;
+      case CommonConstants.Broker.Request.PQL:
+        requestJson.put("pql", query);
+        break;
+      default:
+        throw new UnsupportedOperationException("Unsupported query syntax - " 
+ querySyntax);
+    }
+    if (traceEnabled != null && !traceEnabled.isEmpty()) {
+      requestJson.put("trace", traceEnabled);
+    }
+    if (queryOptions != null && !queryOptions.isEmpty()) {
+      requestJson.put("queryOptions", queryOptions);
+    }
+    return requestJson;
+  }
+
+  private String getQueryURL(String hostName, String port, String querySyntax) 
{
+    switch (querySyntax) {
+      case CommonConstants.Broker.Request.SQL:
+        return String.format("http://%s:%s/query/sql";, hostName, port);
+      case CommonConstants.Broker.Request.PQL:
+        return String.format("http://%s:%s/query";, hostName, port);
+      default:
+        throw new UnsupportedOperationException("Unsupported query syntax - " 
+ querySyntax);
+    }
   }
 
   public String sendPostRaw(String urlStr, String requestStr, Map<String, 
String> headers) {
@@ -169,7 +258,7 @@ public class PqlQueryResource {
       conn.setRequestProperty("Accept-Encoding", "gzip");
 
       final String string = requestStr;
-      final byte[] requestBytes = string.getBytes("UTF-8");
+      final byte[] requestBytes = string.getBytes(StandardCharsets.UTF_8);
       conn.setRequestProperty("Content-Length", 
String.valueOf(requestBytes.length));
       conn.setRequestProperty("http.keepAlive", String.valueOf(true));
       conn.setRequestProperty("default", String.valueOf(true));
@@ -196,13 +285,13 @@ public class PqlQueryResource {
       }
       final byte[] bytes = drain(new 
BufferedInputStream(conn.getInputStream()));
 
-      final String output = new String(bytes, "UTF-8");
+      final String output = new String(bytes, StandardCharsets.UTF_8);
       /*if (LOG.isDebugEnabled()){
         LOGGER.debug("The response from the server is - " + output);
       }*/
       return output;
     } catch (final Exception ex) {
-      LOGGER.error("Caught exception while sending pql request", ex);
+      LOGGER.error("Caught exception while sending query request", ex);
       Utils.rethrowException(ex);
       throw new AssertionError("Should not reach this");
     } finally {
@@ -227,25 +316,17 @@ public class PqlQueryResource {
     }
   }
 
-  public String sendPQLRaw(String url, String pqlRequest, String traceEnabled, 
String queryOptions) {
+  public String sendRequestRaw(String url, String query, ObjectNode 
requestJson) {
     try {
       final long startTime = System.currentTimeMillis();
-      ObjectNode bqlJson = JsonUtils.newObjectNode().put("pql", pqlRequest);
-      if (traceEnabled != null && !traceEnabled.isEmpty()) {
-        bqlJson.put("trace", traceEnabled);
-      }
-      if (queryOptions != null && !queryOptions.isEmpty()) {
-        bqlJson.put("queryOptions", queryOptions);
-      }
-
-      final String pinotResultString = sendPostRaw(url, bqlJson.toString(), 
null);
+      final String pinotResultString = sendPostRaw(url, 
requestJson.toString(), null);
 
-      final long bqlQueryTime = System.currentTimeMillis() - startTime;
-      LOGGER.info("BQL: " + pqlRequest + " Time: " + bqlQueryTime);
+      final long queryTime = System.currentTimeMillis() - startTime;
+      LOGGER.info("Query: " + query + " Time: " + queryTime);
 
       return pinotResultString;
     } catch (final Exception ex) {
-      LOGGER.error("Caught exception in sendPQLRaw", ex);
+      LOGGER.error("Caught exception in sendQueryRaw", ex);
       Utils.rethrowException(ex);
       throw new AssertionError("Should not reach this");
     }
diff --git a/pinot-controller/src/main/resources/static/js/init.js 
b/pinot-controller/src/main/resources/static/js/init.js
index daddfe3..96dc4e2 100644
--- a/pinot-controller/src/main/resources/static/js/init.js
+++ b/pinot-controller/src/main/resources/static/js/init.js
@@ -67,20 +67,9 @@ $(document).ready(function() {
     // execute query and draw the results
     var query = EDITOR.getValue().trim();
     var traceEnabled = document.getElementById('trace-enabled').checked;
-    var groupByModeSQL = document.getElementById('group-by-mode-sql').checked;
-    var responseFormatSQL = 
document.getElementById('response-format-sql').checked;
-    var queryOptions = undefined;
-    if (groupByModeSQL === true) {
-      queryOptions = "groupByMode=sql";
-    }
-    if (responseFormatSQL === true) {
-      if (queryOptions === undefined) {
-        queryOptions = "responseFormat=sql";
-      } else {
-        queryOptions = queryOptions + ";responseFormat=sql";
-      }
-    }
-    HELPERS.executeQuery(query, traceEnabled, queryOptions, function(data) {
+    var querySyntaxPQL = document.getElementById('pql').checked;
+
+    HELPERS.executeQuery(query, querySyntaxPQL, traceEnabled, function(data) {
       RESULTS.setValue(js_beautify(data, JS_BEAUTIFY_SETTINGS));
 
       var queryResponse = null;
@@ -98,41 +87,49 @@ $(document).ready(function() {
 
       var dataArray = [];
       var columnList = [];
-
-      if (queryResponse) {
-        if (queryResponse["selectionResults"]) {
-          // Selection query
-          columnList = _.map(queryResponse.selectionResults.columns, function 
(columnName) {
-            return {"title": columnName};
-          });
-          dataArray = queryResponse.selectionResults.results;
-        } else if (queryResponse["aggregationResults"] && 
queryResponse.aggregationResults.length > 0
-            && !queryResponse.aggregationResults[0]["groupByResult"]) {
-          // Simple aggregation query
-          columnList = _.map(queryResponse.aggregationResults, function 
(aggregationResult) {
-            return {"title": aggregationResult.function};
-          });
-
-          dataArray.push(_.map(queryResponse.aggregationResults, function 
(aggregationResult) {
-            return aggregationResult.value;
-          }));
-        } else if (queryResponse["aggregationResults"] && 
queryResponse.aggregationResults.length > 0
-            && queryResponse.aggregationResults[0]["groupByResult"]) {
-          // Aggregation group by query
-          var columns = queryResponse.aggregationResults[0].groupByColumns;
-          columns.push(queryResponse.aggregationResults[0].function);
-          columnList = _.map(columns, function (columnName) {
+      if (querySyntaxPQL === true) {
+        if (queryResponse) {
+          if (queryResponse["selectionResults"]) {
+            // Selection query
+            columnList = _.map(queryResponse.selectionResults.columns, 
function (columnName) {
+              return {"title": columnName};
+            });
+            dataArray = queryResponse.selectionResults.results;
+          } else if (queryResponse["aggregationResults"] && 
queryResponse.aggregationResults.length > 0
+              && !queryResponse.aggregationResults[0]["groupByResult"]) {
+            // Simple aggregation query
+            columnList = _.map(queryResponse.aggregationResults, function 
(aggregationResult) {
+              return {"title": aggregationResult.function};
+            });
+
+            dataArray.push(_.map(queryResponse.aggregationResults, function 
(aggregationResult) {
+              return aggregationResult.value;
+            }));
+          } else if (queryResponse["aggregationResults"] && 
queryResponse.aggregationResults.length > 0
+              && queryResponse.aggregationResults[0]["groupByResult"]) {
+            // Aggregation group by query
+            var columns = queryResponse.aggregationResults[0].groupByColumns;
+            columns.push(queryResponse.aggregationResults[0].function);
+            columnList = _.map(columns, function (columnName) {
+              return {"title": columnName};
+            });
+
+            dataArray = 
_.map(queryResponse.aggregationResults[0].groupByResult, function 
(aggregationGroup) {
+              var row = aggregationGroup.group;
+              row.push(aggregationGroup.value);
+              return row;
+            });
+          }
+        }
+      } else {
+        if (queryResponse["resultTable"] && queryResponse.resultTable["rows"]
+          && queryResponse.resultTable.rows.length > 0) {
+          columnList = _.map(queryResponse.resultTable.dataSchema.columnNames, 
function (columnName) {
             return {"title": columnName};
           });
-
-          dataArray = _.map(queryResponse.aggregationResults[0].groupByResult, 
function (aggregationGroup) {
-            var row = aggregationGroup.group;
-            row.push(aggregationGroup.value);
-            return row;
-          });
+          dataArray = queryResponse.resultTable.rows;
         }
       }
-
       HELPERS.resetResultsTable();
 
       table = $('#query-results-table').DataTable({
@@ -214,13 +211,22 @@ var HELPERS = {
     var query = EDITOR.getValue().trim();
   },
 
-  executeQuery: function(query, traceEnabled, queryOptions, callback) {
-    var url = "/pql";
-    var params = JSON.stringify({
-      "pql": query,
-      "trace": traceEnabled,
-      "queryOptions" : queryOptions
-    });
+  executeQuery: function(query, querySyntaxPQL, traceEnabled, callback) {
+    var url = undefined;
+    var params = undefined;
+    if (querySyntaxPQL === true) {
+      url = "/pql";
+      params = JSON.stringify({
+        "pql": query,
+        "trace": traceEnabled
+      });
+    } else {
+      url = "/sql";
+      params = JSON.stringify({
+        "sql": query,
+        "trace": traceEnabled
+      });
+    }
     $.ajax({
       type: 'POST',
       url: url,
diff --git a/pinot-controller/src/main/resources/static/query/index.html 
b/pinot-controller/src/main/resources/static/query/index.html
index 0e43c56..aa142f4 100644
--- a/pinot-controller/src/main/resources/static/query/index.html
+++ b/pinot-controller/src/main/resources/static/query/index.html
@@ -79,11 +79,8 @@
           <div class="small-2 columns" title="Enables tracing">
             <input type=checkbox id="trace-enabled">&nbsp;&nbsp;Tracing</input>
           </div>
-          <div class="small-3 columns" title="Sets groupByMode=sql in 
queryOptions (default pql)">
-            <input type=checkbox id="group-by-mode-sql">&nbsp;&nbsp;Group By 
Mode : SQL</input>
-          </div>
-          <div class="small-4 columns" title="Sets responseFormat=sql in 
queryOptions (default pql)">
-            <input type=checkbox id="response-format-sql">&nbsp;&nbsp;Query 
Response Format : SQL</input>
+          <div class="small-3 columns" title="Send query to /pql endpoint 
(default to /sql)">
+            <input type=checkbox id="pql">&nbsp;&nbsp;Query Syntax: PQL</input>
           </div>
           <div class="small-2 columns"><a href="#" id="execute-query" 
class="button round success small">Run Query</a>
           </div>
diff --git a/pinot-controller/src/main/resources/webapp/index.html 
b/pinot-controller/src/main/resources/webapp/index.html
index 3662d0f..5401435 100644
--- a/pinot-controller/src/main/resources/webapp/index.html
+++ b/pinot-controller/src/main/resources/webapp/index.html
@@ -75,11 +75,8 @@
           <div class="small-2 columns" title="Enables tracing">
             <input type=checkbox id="trace-enabled">&nbsp;&nbsp;Tracing</input>
           </div>
-          <div class="small-3 columns" title="Sets groupByMode=sql in 
queryOptions (default pql)">
-            <input type=checkbox id="group-by-mode-sql">&nbsp;&nbsp;Group By 
Mode : SQL</input>
-          </div>
-          <div class="small-4 columns" title="Sets responseFormat=sql in 
queryOptions (default pql)">
-            <input type=checkbox id="response-format-sql">&nbsp;&nbsp;Query 
Response Format : SQL</input>
+          <div class="small-3 columns" title="Send query to /pql endpoint 
(default to /sql)">
+            <input type=checkbox id="pql">&nbsp;&nbsp;Query Syntax: PQL</input>
           </div>
           <div class="small-2 columns"><a href="#" id="execute-query" 
class="button round success small">Run Query</a>
           </div>
diff --git a/pinot-controller/src/main/resources/webapp/js/init.js 
b/pinot-controller/src/main/resources/webapp/js/init.js
index 6775aaa..e75ac6b 100644
--- a/pinot-controller/src/main/resources/webapp/js/init.js
+++ b/pinot-controller/src/main/resources/webapp/js/init.js
@@ -65,20 +65,8 @@ $(document).ready(function() {
     // execute query and draw the results
     var query = EDITOR.getValue().trim();
     var traceEnabled = document.getElementById('trace-enabled').checked;
-    var groupByModeSQL = document.getElementById('group-by-mode-sql').checked;
-    var responseFormatSQL = 
document.getElementById('response-format-sql').checked;
-    var queryOptions = undefined;
-    if (groupByModeSQL === true) {
-      queryOptions = "groupByMode=sql";
-    }
-    if (responseFormatSQL === true) {
-      if (queryOptions === undefined) {
-        queryOptions = "responseFormat=sql";
-      } else {
-        queryOptions = queryOptions + ";responseFormat=sql";
-      }
-    }
-    HELPERS.executeQuery(query, traceEnabled, queryOptions, function(data) {
+    var querySyntaxPQL = document.getElementById('pql').checked;
+    HELPERS.executeQuery(query, querySyntaxPQL, traceEnabled, function(data) {
       RESULTS.setValue(js_beautify(data, JS_BEAUTIFY_SETTINGS));
     })
   });
@@ -135,13 +123,22 @@ var HELPERS = {
     var query = EDITOR.getValue().trim();
   },
 
-  executeQuery: function(query, traceEnabled, queryOptions, callback) {
-    var url = "/pql";
-    var params = JSON.stringify({
-      "pql": query,
-      "trace": traceEnabled,
-      "queryOptions" : queryOptions
-    });
+  executeQuery: function(query, querySyntaxPQL, traceEnabled, callback) {
+    var url = undefined;
+    var params = undefined;
+    if (querySyntaxPQL === true) {
+      url = "/pql";
+      params = JSON.stringify({
+        "pql": query,
+        "trace": traceEnabled
+      });
+    } else {
+      url = "/sql";
+      params = JSON.stringify({
+        "sql": query,
+        "trace": traceEnabled
+      });
+    }
     $.ajax({
       type: 'POST',
       url: url,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to