This is an automated email from the ASF dual-hosted git repository. chunwei pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new f99ff5f [CALCITE-3246] NullPointerException while deserializing udf operator (Wang Yanlin). f99ff5f is described below commit f99ff5f4b5bb305f5fd3726d212363f75e8150f2 Author: yanzhi <yanzhi....@antfin.com> AuthorDate: Tue Aug 13 13:56:44 2019 +0800 [CALCITE-3246] NullPointerException while deserializing udf operator (Wang Yanlin). --- .../apache/calcite/rel/externalize/RelJson.java | 14 ++++++---- .../calcite/rel/externalize/RelJsonReader.java | 2 +- .../org/apache/calcite/plan/RelWriterTest.java | 32 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java index c7fe76f..abb240e 100644 --- a/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java +++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java @@ -440,13 +440,15 @@ public class RelJson { final Map<String, Object> opMap = (Map) map.get("op"); final RelDataTypeFactory typeFactory = cluster.getTypeFactory(); if (opMap != null) { - final String op = (String) opMap.get("name"); + if (map.containsKey("class")) { + opMap.put("class", map.get("class")); + } final List operands = (List) map.get("operands"); final List<RexNode> rexOperands = toRexList(relInput, operands); final Object jsonType = map.get("type"); final Map window = (Map) map.get("window"); if (window != null) { - final SqlAggFunction operator = toAggregation(relInput, op, opMap); + final SqlAggFunction operator = toAggregation(opMap); final RelDataType type = toType(typeFactory, jsonType); final List<RexNode> partitionKeys = toRexList(relInput, (List) window.get("partition")); final List<RexFieldCollation> orderKeys = @@ -473,7 +475,7 @@ public class RelJson { ImmutableList.copyOf(orderKeys), lowerBound, upperBound, physical, true, false, distinct, false); } else { - final SqlOperator operator = toOp(relInput, opMap); + final SqlOperator operator = toOp(opMap); final RelDataType type; if (jsonType != null) { type = toType(typeFactory, jsonType); @@ -607,7 +609,7 @@ public class RelJson { return list; } - SqlOperator toOp(RelInput relInput, Map<String, Object> map) { + SqlOperator toOp(Map<String, Object> map) { // in case different operator has the same kind, check with both name and kind. String name = map.get("name").toString(); String kind = map.get("kind").toString(); @@ -633,8 +635,8 @@ public class RelJson { return null; } - SqlAggFunction toAggregation(RelInput relInput, String agg, Map<String, Object> map) { - return (SqlAggFunction) toOp(relInput, map); + SqlAggFunction toAggregation(Map<String, Object> map) { + return (SqlAggFunction) toOp(map); } private Map toJson(SqlOperator operator) { diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java index e7a73a8..4cef915 100644 --- a/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java +++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java @@ -275,7 +275,7 @@ public class RelJsonReader { private AggregateCall toAggCall(RelInput relInput, Map<String, Object> jsonAggCall) { final Map<String, Object> aggMap = (Map) jsonAggCall.get("agg"); final SqlAggFunction aggregation = - relJson.toAggregation(relInput, (String) aggMap.get("name"), aggMap); + relJson.toAggregation(aggMap); final Boolean distinct = (Boolean) jsonAggCall.get("distinct"); @SuppressWarnings("unchecked") final List<Integer> operands = (List<Integer>) jsonAggCall.get("operands"); diff --git a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java index 0e74702..3feb934 100644 --- a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java +++ b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java @@ -41,6 +41,7 @@ import org.apache.calcite.sql.fun.SqlTrimFunction; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.test.JdbcTest; +import org.apache.calcite.test.MockSqlOperatorTable; import org.apache.calcite.test.RelBuilderTest; import org.apache.calcite.tools.FrameworkConfig; import org.apache.calcite.tools.Frameworks; @@ -581,6 +582,37 @@ public class RelWriterTest { assertThat(s, isLinux(expected)); } + @Test public void testUdf() { + final FrameworkConfig config = RelBuilderTest.config().build(); + final RelBuilder builder = RelBuilder.create(config); + final RelNode rel = builder + .scan("EMP") + .project( + builder.call(new MockSqlOperatorTable.MyFunction(), + builder.field("EMPNO"))) + .build(); + RelJsonWriter jsonWriter = new RelJsonWriter(); + rel.explain(jsonWriter); + String relJson = jsonWriter.asString(); + String s = + Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> { + final RelJsonReader reader = new RelJsonReader( + cluster, getSchema(rel), rootSchema); + RelNode node; + try { + node = reader.read(relJson); + } catch (IOException e) { + throw TestUtil.rethrow(e); + } + return RelOptUtil.dumpPlan("", node, SqlExplainFormat.TEXT, + SqlExplainLevel.EXPPLAN_ATTRIBUTES); + }); + final String expected = "" + + "LogicalProject($f0=[MYFUN($0)])\n" + + " LogicalTableScan(table=[[scott, EMP]])\n"; + assertThat(s, isLinux(expected)); + } + /** Returns the schema of a {@link org.apache.calcite.rel.core.TableScan} * in this plan, or null if there are no scans. */ private RelOptSchema getSchema(RelNode rel) {