fx19880617 commented on a change in pull request #5513:
URL: https://github.com/apache/incubator-pinot/pull/5513#discussion_r436894620



##########
File path: 
pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
##########
@@ -676,14 +678,25 @@ protected static Expression 
invokeCompileTimeFunctionExpression(Expression funcE
       try {
         FunctionInvoker invoker = new FunctionInvoker(functionInfo);
         Object result = invoker.process(arguments);
-        if (result instanceof String) {
-          result = String.format("'%s'", result);
-        }
         return RequestUtils.getLiteralExpression(result);
       } catch (Exception e) {
         throw new SqlCompilationException(new 
IllegalArgumentException("Unsupported function - " + funcName, e));
       }
     }
     return funcExpr;
   }
+
+  public static boolean isLiteralOnlyExpression(Expression e) {
+    if (e.getType() == ExpressionType.LITERAL) {
+      return true;
+    }
+    if (e.getType() == ExpressionType.FUNCTION) {
+      Function functionCall = e.getFunctionCall();
+      if (functionCall.getOperator().equalsIgnoreCase(SqlKind.AS.toString())) {

Review comment:
       Yes, the CalciteSQLParser already evaluated the transform function with 
literals and replace it with literal.
   So the only left over is to handle here is `Literal` and `Function` `AS`.

##########
File path: 
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java
##########
@@ -435,6 +455,116 @@ static void handleQueryLimitOverride(BrokerRequest 
brokerRequest, int queryLimit
     }
   }
 
+  /**
+   * Check if a SQL parsed BrokerRequest is a literal only query.
+   * @param brokerRequest
+   * @return true if this query selects only Literals
+   *
+   */
+  @VisibleForTesting
+  static boolean isLiteralOnlyQuery(BrokerRequest brokerRequest) {
+    if (brokerRequest.getPinotQuery() != null) {

Review comment:
       sure 

##########
File path: 
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java
##########
@@ -435,6 +455,116 @@ static void handleQueryLimitOverride(BrokerRequest 
brokerRequest, int queryLimit
     }
   }
 
+  /**
+   * Check if a SQL parsed BrokerRequest is a literal only query.
+   * @param brokerRequest
+   * @return true if this query selects only Literals
+   *
+   */
+  @VisibleForTesting
+  static boolean isLiteralOnlyQuery(BrokerRequest brokerRequest) {
+    if (brokerRequest.getPinotQuery() != null) {

Review comment:
       added

##########
File path: 
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java
##########
@@ -184,6 +192,18 @@ public BrokerResponse handleRequest(JsonNode request, 
@Nullable RequesterIdentit
       requestStatistics.setErrorCode(QueryException.PQL_PARSING_ERROR_CODE);
       return new 
BrokerResponseNative(QueryException.getException(QueryException.PQL_PARSING_ERROR,
 e));
     }
+    if (isLiteralOnlyQuery(brokerRequest)) {
+      LOGGER.info("Request {} contains only Literal, skipping server query: 
{}", requestId, query);
+      try {
+        BrokerResponse brokerResponse =
+            processLiteralOnlyBrokerRequest(brokerRequest, 
compilationStartTimeNs, requestStatistics);
+        return brokerResponse;
+      } catch (IllegalStateException e) {

Review comment:
       We only catch the behavior that process literal functions failure.

##########
File path: 
pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
##########
@@ -278,7 +278,9 @@ private static PinotQuery 
compileCalciteSqlToPinotQuery(String sql) {
           pinotQuery.setOffset(Integer.valueOf(((SqlNumericLiteral) 
selectSqlNode.getOffset()).toValue()));
         }
         DataSource dataSource = new DataSource();
-        dataSource.setTableName(selectSqlNode.getFrom().toString());
+        if (selectSqlNode.getFrom() != null) {

Review comment:
       From sql standard, it's ok if it's null, the query should not fail if it 
contains no literals.

##########
File path: 
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java
##########
@@ -435,6 +455,116 @@ static void handleQueryLimitOverride(BrokerRequest 
brokerRequest, int queryLimit
     }
   }
 
+  /**
+   * Check if a SQL parsed BrokerRequest is a literal only query.
+   * @param brokerRequest
+   * @return true if this query selects only Literals
+   *
+   */
+  @VisibleForTesting
+  static boolean isLiteralOnlyQuery(BrokerRequest brokerRequest) {
+    if (brokerRequest.getPinotQuery() != null) {
+      for (Expression e: brokerRequest.getPinotQuery().getSelectList()) {
+        if (!CalciteSqlParser.isLiteralOnlyExpression(e)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Compute BrokerResponse for literal only query.
+   *
+   * @param brokerRequest
+   * @param compilationStartTimeNs
+   * @param requestStatistics
+   * @return BrokerResponse
+   */
+  private BrokerResponse processLiteralOnlyBrokerRequest(BrokerRequest 
brokerRequest, long compilationStartTimeNs,
+      RequestStatistics requestStatistics)
+      throws IllegalStateException {
+    System.out.println("brokerRequest = " + brokerRequest.toString());
+    BrokerResponseNative brokerResponse = new BrokerResponseNative();
+    List<String> columnNames = new ArrayList<>();
+    List<DataSchema.ColumnDataType> columnTypes = new ArrayList<>();
+    List<Object> row = new ArrayList<>();
+    for (Expression e : brokerRequest.getPinotQuery().getSelectList()) {
+      computeResultsForExpression(e, columnNames, columnTypes, row);
+    }
+    DataSchema dataSchema =
+        new DataSchema(columnNames.toArray(new String[0]), 
columnTypes.toArray(new DataSchema.ColumnDataType[0]));
+    List<Object[]> rows = new ArrayList<>();
+    rows.add(row.toArray());
+    ResultTable resultTable = new ResultTable(dataSchema, rows);
+    brokerResponse.setResultTable(resultTable);
+
+    long totalTimeMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - 
compilationStartTimeNs);
+    brokerResponse.setTimeUsedMs(totalTimeMs);
+    requestStatistics.setQueryProcessingTime(totalTimeMs);
+    requestStatistics.setStatistics(brokerResponse);
+    return brokerResponse;
+  }
+
+  private void computeResultsForExpression(Expression e, List<String> 
columnNames, List<DataSchema.ColumnDataType> columnTypes,
+      List<Object> row) {
+    if (e.getType() == ExpressionType.LITERAL) {
+      computeResultsForLiteral(e.getLiteral(), columnNames, columnTypes, row);
+    }
+    if (e.getType() == ExpressionType.FUNCTION) {
+      if 
(e.getFunctionCall().getOperator().equalsIgnoreCase(SqlKind.AS.toString())) {
+        String columnName = 
e.getFunctionCall().getOperands().get(1).getIdentifier().getName();
+        computeResultsForExpression(e.getFunctionCall().getOperands().get(0), 
columnNames, columnTypes, row);
+        columnNames.set(columnNames.size() - 1, columnName);
+      } else {
+        throw new IllegalStateException(
+            "No able to compute results for function - " + 
e.getFunctionCall().getOperator());
+      }
+    }
+  }
+
+  private void computeResultsForLiteral(Literal literal, List<String> 
columnNames, List<DataSchema.ColumnDataType> columnTypes,
+      List<Object> row) {
+    Object fieldValue = literal.getFieldValue();
+    columnNames.add(fieldValue.toString());
+    switch (literal.getSetField()) {
+      case SHORT_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.INT);
+        row.add((int) literal.getShortValue());
+        break;
+      case INT_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.INT);
+        row.add(literal.getIntValue());
+        break;
+      case LONG_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.LONG);
+        row.add(literal.getLongValue());
+        break;
+      case DOUBLE_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.DOUBLE);
+        row.add(literal.getDoubleValue());
+        break;
+      case BOOL_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.STRING);
+        row.add(new Boolean(literal.getBoolValue()).toString());
+        break;
+      case STRING_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.STRING);
+        System.out.println("literal.getStringValue() = " + 
literal.getStringValue());
+        row.add(literal.getStringValue());
+        break;
+      case BINARY_VALUE:
+        columnTypes.add(DataSchema.ColumnDataType.BYTES);
+        row.add(BytesUtils.toHexString(literal.getBinaryValue()));
+        break;
+      case BYTE_VALUE:

Review comment:
       Make sense!

##########
File path: 
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java
##########
@@ -184,6 +192,18 @@ public BrokerResponse handleRequest(JsonNode request, 
@Nullable RequesterIdentit
       requestStatistics.setErrorCode(QueryException.PQL_PARSING_ERROR_CODE);
       return new 
BrokerResponseNative(QueryException.getException(QueryException.PQL_PARSING_ERROR,
 e));
     }
+    if (isLiteralOnlyQuery(brokerRequest)) {
+      LOGGER.info("Request {} contains only Literal, skipping server query: 
{}", requestId, query);

Review comment:
       Changed this log to debug level.
   For the code from `376-405`, I feel it makes too many assumptions which 
current broker query doesn't honor. I prefer to keep them separately.
   
   

##########
File path: 
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java
##########
@@ -184,6 +192,18 @@ public BrokerResponse handleRequest(JsonNode request, 
@Nullable RequesterIdentit
       requestStatistics.setErrorCode(QueryException.PQL_PARSING_ERROR_CODE);
       return new 
BrokerResponseNative(QueryException.getException(QueryException.PQL_PARSING_ERROR,
 e));
     }
+    if (isLiteralOnlyQuery(brokerRequest)) {
+      LOGGER.info("Request {} contains only Literal, skipping server query: 
{}", requestId, query);

Review comment:
       Changed this log to debug level.
   For the code from `376-405`, I feel it makes too many assumptions which 
current broker query doesn't honor(e.g. table name is not a must here). I 
prefer to keep them separately.
   
   




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org
For additional commands, e-mail: commits-h...@pinot.apache.org

Reply via email to