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