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

mmior 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 4954216  [CALCITE-3177]Ensure correct deserialization of relational 
algebra.
4954216 is described below

commit 4954216c71a6262728ad6ed4792d4ac7b9ec7b71
Author: yanzhi <[email protected]>
AuthorDate: Thu Jul 25 10:03:43 2019 +0800

    [CALCITE-3177]Ensure correct deserialization of relational algebra.
---
 .../apache/calcite/rel/externalize/RelJson.java    | 45 ++++++++----
 .../calcite/rel/externalize/RelJsonReader.java     |  4 +-
 .../org/apache/calcite/plan/RelWriterTest.java     | 80 +++++++++++++++++++---
 3 files changed, 105 insertions(+), 24 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 169ecb0..c7fe76f 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
@@ -46,12 +46,15 @@ import org.apache.calcite.rex.RexWindow;
 import org.apache.calcite.rex.RexWindowBound;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSyntax;
 import org.apache.calcite.sql.SqlWindow;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.validate.SqlNameMatchers;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.JsonBuilder;
 import org.apache.calcite.util.Util;
@@ -434,15 +437,16 @@ public class RelJson {
       return null;
     } else if (o instanceof Map) {
       Map map = (Map) o;
-      final String op = (String) map.get("op");
+      final Map<String, Object> opMap = (Map) map.get("op");
       final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
-      if (op != null) {
+      if (opMap != null) {
+        final String op = (String) opMap.get("name");
         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, map);
+          final SqlAggFunction operator = toAggregation(relInput, op, opMap);
           final RelDataType type = toType(typeFactory, jsonType);
           final List<RexNode> partitionKeys = toRexList(relInput, (List) 
window.get("partition"));
           final List<RexFieldCollation> orderKeys =
@@ -469,7 +473,7 @@ public class RelJson {
               ImmutableList.copyOf(orderKeys), lowerBound, upperBound, 
physical,
               true, false, distinct, false);
         } else {
-          final SqlOperator operator = toOp(relInput, op, map);
+          final SqlOperator operator = toOp(relInput, opMap);
           final RelDataType type;
           if (jsonType != null) {
             type = toType(typeFactory, jsonType);
@@ -603,13 +607,22 @@ public class RelJson {
     return list;
   }
 
-  SqlOperator toOp(RelInput relInput, String op, Map<String, Object> map) {
-    // TODO: build a map, for more efficient lookup
-    // TODO: look up based on SqlKind
-    final List<SqlOperator> operatorList =
-        SqlStdOperatorTable.instance().getOperatorList();
-    for (SqlOperator operator : operatorList) {
-      if (operator.getName().equals(op)) {
+  SqlOperator toOp(RelInput relInput, 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();
+    String syntax = map.get("syntax").toString();
+    SqlKind sqlKind = SqlKind.valueOf(kind);
+    SqlSyntax  sqlSyntax = SqlSyntax.valueOf(syntax);
+    List<SqlOperator> operators = new ArrayList<>();
+    SqlStdOperatorTable.instance().lookupOperatorOverloads(
+        new SqlIdentifier(name, new SqlParserPos(0, 0)),
+        null,
+        sqlSyntax,
+        operators,
+        SqlNameMatchers.liberal());
+    for (SqlOperator operator: operators) {
+      if (operator.kind == sqlKind) {
         return operator;
       }
     }
@@ -621,12 +634,16 @@ public class RelJson {
   }
 
   SqlAggFunction toAggregation(RelInput relInput, String agg, Map<String, 
Object> map) {
-    return (SqlAggFunction) toOp(relInput, agg, map);
+    return (SqlAggFunction) toOp(relInput, map);
   }
 
-  private String toJson(SqlOperator operator) {
+  private Map toJson(SqlOperator operator) {
     // User-defined operators are not yet handled.
-    return operator.getName();
+    Map map = jsonBuilder.map();
+    map.put("name", operator.getName());
+    map.put("kind", operator.kind.toString());
+    map.put("syntax", operator.getSyntax().toString());
+    return map;
   }
 }
 
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 b7d7e8a..e7a73a8 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
@@ -273,9 +273,9 @@ public class RelJsonReader {
   }
 
   private AggregateCall toAggCall(RelInput relInput, Map<String, Object> 
jsonAggCall) {
-    final String aggName = (String) jsonAggCall.get("agg");
+    final Map<String, Object> aggMap = (Map) jsonAggCall.get("agg");
     final SqlAggFunction aggregation =
-        relJson.toAggregation(relInput, aggName, jsonAggCall);
+        relJson.toAggregation(relInput, (String) aggMap.get("name"), 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 4734413..0e74702 100644
--- a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
@@ -82,7 +82,11 @@ public class RelWriterTest {
       + "      \"id\": \"1\",\n"
       + "      \"relOp\": \"LogicalFilter\",\n"
       + "      \"condition\": {\n"
-      + "        \"op\": \"=\",\n"
+      + "        \"op\": {\n"
+      + "          \"name\": \"=\",\n"
+      + "          \"kind\": \"EQUALS\",\n"
+      + "          \"syntax\": \"BINARY\"\n"
+      + "        },\n"
       + "        \"operands\": [\n"
       + "          {\n"
       + "            \"input\": 1,\n"
@@ -106,7 +110,11 @@ public class RelWriterTest {
       + "      ],\n"
       + "      \"aggs\": [\n"
       + "        {\n"
-      + "          \"agg\": \"COUNT\",\n"
+      + "          \"agg\": {\n"
+      + "            \"name\": \"COUNT\",\n"
+      + "            \"kind\": \"COUNT\",\n"
+      + "            \"syntax\": \"FUNCTION_STAR\"\n"
+      + "          },\n"
       + "          \"type\": {\n"
       + "            \"type\": \"BIGINT\",\n"
       + "            \"nullable\": false\n"
@@ -117,7 +125,11 @@ public class RelWriterTest {
       + "          ]\n"
       + "        },\n"
       + "        {\n"
-      + "          \"agg\": \"COUNT\",\n"
+      + "          \"agg\": {\n"
+      + "            \"name\": \"COUNT\",\n"
+      + "            \"kind\": \"COUNT\",\n"
+      + "            \"syntax\": \"FUNCTION_STAR\"\n"
+      + "          },\n"
       + "          \"type\": {\n"
       + "            \"type\": \"BIGINT\",\n"
       + "            \"nullable\": false\n"
@@ -145,7 +157,11 @@ public class RelWriterTest {
       + "      \"id\": \"1\",\n"
       + "      \"relOp\": \"LogicalFilter\",\n"
       + "      \"condition\": {\n"
-      + "        \"op\": \"=\",\n"
+      + "        \"op\": {"
+      + "            \"name\": \"=\",\n"
+      + "            \"kind\": \"EQUALS\",\n"
+      + "            \"syntax\": \"BINARY\"\n"
+      + "          },\n"
       + "        \"operands\": [\n"
       + "          {\n"
       + "            \"input\": 1,\n"
@@ -166,7 +182,11 @@ public class RelWriterTest {
       + "      ],\n"
       + "      \"aggs\": [\n"
       + "        {\n"
-      + "          \"agg\": \"COUNT\",\n"
+      + "        \"agg\": {\n"
+      + "            \"name\": \"COUNT\",\n"
+      + "            \"kind\": \"COUNT\",\n"
+      + "            \"syntax\": \"FUNCTION_STAR\"\n"
+      + "          },\n"
       + "          \"type\": {\n"
       + "            \"type\": \"BIGINT\",\n"
       + "            \"nullable\": false\n"
@@ -177,7 +197,11 @@ public class RelWriterTest {
       + "          ]\n"
       + "        },\n"
       + "        {\n"
-      + "          \"agg\": \"COUNT\",\n"
+      + "        \"agg\": {\n"
+      + "            \"name\": \"COUNT\",\n"
+      + "            \"kind\": \"COUNT\",\n"
+      + "            \"syntax\": \"FUNCTION_STAR\"\n"
+      + "          },\n"
       + "          \"type\": {\n"
       + "            \"type\": \"BIGINT\",\n"
       + "            \"nullable\": false\n"
@@ -215,7 +239,11 @@ public class RelWriterTest {
       + "          \"name\": \"$0\"\n"
       + "        },\n"
       + "        {\n"
-      + "          \"op\": \"COUNT\",\n"
+      + "          \"op\": {\n"
+      + "            \"name\": \"COUNT\",\n"
+      + "            \"kind\": \"COUNT\",\n"
+      + "            \"syntax\": \"FUNCTION_STAR\"\n"
+      + "          },\n"
       + "          \"operands\": [\n"
       + "            {\n"
       + "              \"input\": 0,\n"
@@ -253,7 +281,11 @@ public class RelWriterTest {
       + "          }\n"
       + "        },\n"
       + "        {\n"
-      + "          \"op\": \"SUM\",\n"
+      + "          \"op\": {\n"
+      + "            \"name\": \"SUM\",\n"
+      + "            \"kind\": \"SUM\",\n"
+      + "            \"syntax\": \"FUNCTION\"\n"
+      + "          },\n"
       + "          \"operands\": [\n"
       + "            {\n"
       + "              \"input\": 0,\n"
@@ -517,6 +549,38 @@ public class RelWriterTest {
     assertThat(s, isLinux(expected));
   }
 
+  @Test public void testPlusOperator() {
+    final FrameworkConfig config = RelBuilderTest.config().build();
+    final RelBuilder builder = RelBuilder.create(config);
+    final RelNode rel = builder
+        .scan("EMP")
+        .project(
+            builder.call(SqlStdOperatorTable.PLUS,
+                builder.field("SAL"),
+                builder.literal(10)))
+        .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=[+($5, 10)])\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) {

Reply via email to