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

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


The following commit(s) were added to refs/heads/master by this push:
     new ff2a33318e [multistage] add cast function (#9384)
ff2a33318e is described below

commit ff2a33318edf9669daeb23184c29dd595c8b654e
Author: Rong Rong <walterddr.walter...@gmail.com>
AuthorDate: Tue Sep 13 11:42:17 2022 -0700

    [multistage] add cast function (#9384)
    
    * add CAST by using the DataConversion func
    
    Co-authored-by: Rong Rong <ro...@startree.ai>
---
 .../pinot/query/planner/logical/RexExpression.java | 43 +++++++++++++++++++++-
 .../query/runtime/QueryRunnerExceptionTest.java    |  7 ++--
 .../pinot/query/runtime/QueryRunnerTest.java       |  9 ++++-
 3 files changed, 53 insertions(+), 6 deletions(-)

diff --git 
a/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpression.java
 
b/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpression.java
index d9b04ec06f..32a3608c86 100644
--- 
a/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpression.java
+++ 
b/pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/RexExpression.java
@@ -18,6 +18,7 @@
  */
 package org.apache.pinot.query.planner.logical;
 
+import com.google.common.base.Preconditions;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -30,6 +31,7 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.NlsString;
+import org.apache.pinot.common.utils.PinotDataType;
 import org.apache.pinot.query.planner.serde.ProtoProperties;
 import org.apache.pinot.spi.data.FieldSpec;
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -56,13 +58,50 @@ public interface RexExpression {
       RexCall rexCall = (RexCall) rexNode;
       List<RexExpression> operands = 
rexCall.getOperands().stream().map(RexExpression::toRexExpression)
           .collect(Collectors.toList());
-      return new RexExpression.FunctionCall(rexCall.getKind(), 
toDataType(rexCall.getType()),
-          rexCall.getOperator().getName(), operands);
+      return toRexExpression(rexCall, operands);
     } else {
       throw new IllegalArgumentException("Unsupported RexNode type with 
SqlKind: " + rexNode.getKind());
     }
   }
 
+  static RexExpression toRexExpression(RexCall rexCall, List<RexExpression> 
operands) {
+    switch (rexCall.getKind()) {
+      case CAST:
+        // CAST is being rewritten into "rexCall.CAST<targetType>(inputValue)",
+        //   - e.g. result type has already been converted into the CAST 
RexCall, so we assert single operand.
+        Preconditions.checkState(operands.size() == 1, "CAST takes exactly 2 
arguments");
+        RelDataType castType = rexCall.getType();
+        // add the 2nd argument as the source type info.
+        operands.add(new Literal(FieldSpec.DataType.STRING, 
rexCall.getOperands().get(0).getType().getSqlTypeName(),
+            toPinotDataType(rexCall.getOperands().get(0).getType()).name()));
+        return new RexExpression.FunctionCall(rexCall.getKind(), 
toDataType(rexCall.getType()), "CAST", operands);
+      default:
+        return new RexExpression.FunctionCall(rexCall.getKind(), 
toDataType(rexCall.getType()),
+            rexCall.getOperator().getName(), operands);
+    }
+  }
+
+  static PinotDataType toPinotDataType(RelDataType type) {
+    switch (type.getSqlTypeName()) {
+      case INTEGER:
+        return PinotDataType.INTEGER;
+      case BIGINT:
+        return PinotDataType.LONG;
+      case FLOAT:
+        return PinotDataType.FLOAT;
+      case DOUBLE:
+        return PinotDataType.DOUBLE;
+      case CHAR:
+      case VARCHAR:
+        return PinotDataType.STRING;
+      case BOOLEAN:
+        return PinotDataType.BOOLEAN;
+      default:
+        // TODO: do not assume byte type.
+        return PinotDataType.BYTES;
+    }
+  }
+
   static RexExpression toRexExpression(AggregateCall aggCall) {
     List<RexExpression> operands = 
aggCall.getArgList().stream().map(InputRef::new).collect(Collectors.toList());
     return new RexExpression.FunctionCall(aggCall.getAggregation().getKind(), 
toDataType(aggCall.getType()),
diff --git 
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerExceptionTest.java
 
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerExceptionTest.java
index de70190b7f..5b5c084ce5 100644
--- 
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerExceptionTest.java
+++ 
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerExceptionTest.java
@@ -68,9 +68,10 @@ public class QueryRunnerExceptionTest extends 
QueryRunnerTestBase {
   @DataProvider(name = "testDataWithSqlExecutionExceptions")
   private Object[][] provideTestSqlWithExecutionException() {
     return new Object[][] {
-        // default planner will auto-cast string column to numeric on JOIN 
condition, so exception is:
-        // "error while invoking cast function", because the cast cannot be 
done.
-        new Object[]{"SELECT a.col2 - b.col3 FROM a JOIN b ON a.col1 = 
b.col1", "transform function: cast"},
+        // Function with incorrect argument signature should throw runtime 
exception
+        new Object[]{"SELECT least(a.col2, b.col3) FROM a JOIN b ON a.col1 = 
b.col1",
+            "ArithmeticFunctions.least(double,double) with arguments"},
+        // Function that tries to cast String to Number should throw runtime 
exception
         new Object[]{"SELECT a.col2, b.col1 FROM a JOIN b ON a.col1 = b.col3", 
"transform function: cast"},
     };
   }
diff --git 
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
 
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
index 8e5167b007..7ae65076b8 100644
--- 
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
+++ 
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
@@ -183,7 +183,14 @@ public class QueryRunnerTest extends QueryRunnerTestBase {
         new Object[]{"SELECT dateTrunc('DAY', round(a.ts, b.ts)) FROM a JOIN b 
"
             + "ON a.col1 = b.col1 AND a.col2 = b.col2", 15},
 
-        // Distinct value done via GROUP BY with empty expr aggregation list.
+        // Test CAST
+        //   - implicit CAST
+        new Object[]{"SELECT a.col1, a.col2, AVG(a.col3) FROM a GROUP BY 
a.col1, a.col2", 5},
+        //   - explicit CAST
+        new Object[]{"SELECT a.col1, dateTrunc('DAY', CAST(SUM(a.col3) AS 
BIGINT)) FROM a GROUP BY a.col1", 5},
+
+        // Test DISTINCT
+        //   - distinct value done via GROUP BY with empty expr aggregation 
list.
         new Object[]{"SELECT a.col2, a.col3 FROM a JOIN b ON a.col1 = b.col1 "
             + " WHERE b.col3 > 0 GROUP BY a.col2, a.col3", 5},
     };


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

Reply via email to