julianhyde commented on a change in pull request #2709:
URL: https://github.com/apache/calcite/pull/2709#discussion_r798930442



##########
File path: core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java
##########
@@ -776,4 +905,22 @@ private void addRexFieldCollationList(
     map.put("syntax", operator.getSyntax().toString());
     return map;
   }
+
+  /**

Review comment:
       I wouldn't mention the 'functional interface'. Document its purpose, 
which is to translate.
   
   Rename `apply` to something like `translate`. `apply` only made sense when 
this was a `BiFunction`.
   
   In the method javadoc change `Lambda that defines how to transform` to 
`Transforms`. Less is more.
   
   Rename `stringObjectMap` to `map`.
   
    

##########
File path: core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java
##########
@@ -99,7 +102,143 @@
           "org.apache.calcite.adapter.jdbc.JdbcRules$");
 
   public RelJson(@Nullable JsonBuilder jsonBuilder) {
+    this(jsonBuilder, RelJson::inputTranslatorImpl);
+  }
+
+  private static RexNode inputTranslatorImpl(
+      Map<String, Object> stringObjectMap,
+      RexBuilder rexBuilder,
+      List<RelNode> relNodes) {
+    final Integer input = (Integer) stringObjectMap.get("input");
+    if (input != null) {
+      int i = input;
+      for (RelNode inputNode : relNodes) {
+        final RelDataType rowType = inputNode.getRowType();
+        if (i < rowType.getFieldCount()) {
+          final RelDataTypeField field = rowType.getFieldList().get(i);
+          return rexBuilder.makeInputRef(field.getType(), input);
+        }
+        i -= rowType.getFieldCount();
+      }
+      throw new RuntimeException("input field " + input + " is out of range");
+    } else {
+      throw new RuntimeException("input not defined");
+    }
+  }
+
+  public RelJson(@Nullable JsonBuilder jsonBuilder, InputTranslator 
inputTranslator) {
     this.jsonBuilder = jsonBuilder;
+    this.inputTranslator = inputTranslator;
+  }
+
+  /**
+   * Transforms a RexNode tree defined in a map (from a JSON) into a RexNode,
+   * applying a special method to inputs instead of transforming them into 
inputRef.
+   * @param cluster The optimization environment
+   * @param apply is a InputTranslator lambda that transforms the map 
representing input

Review comment:
       rename `apply` parameter to `translator`

##########
File path: core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java
##########
@@ -99,7 +102,143 @@
           "org.apache.calcite.adapter.jdbc.JdbcRules$");
 
   public RelJson(@Nullable JsonBuilder jsonBuilder) {
+    this(jsonBuilder, RelJson::inputTranslatorImpl);
+  }
+
+  private static RexNode inputTranslatorImpl(
+      Map<String, Object> stringObjectMap,
+      RexBuilder rexBuilder,
+      List<RelNode> relNodes) {
+    final Integer input = (Integer) stringObjectMap.get("input");
+    if (input != null) {
+      int i = input;
+      for (RelNode inputNode : relNodes) {
+        final RelDataType rowType = inputNode.getRowType();
+        if (i < rowType.getFieldCount()) {
+          final RelDataTypeField field = rowType.getFieldList().get(i);
+          return rexBuilder.makeInputRef(field.getType(), input);
+        }
+        i -= rowType.getFieldCount();
+      }
+      throw new RuntimeException("input field " + input + " is out of range");
+    } else {
+      throw new RuntimeException("input not defined");
+    }
+  }
+
+  public RelJson(@Nullable JsonBuilder jsonBuilder, InputTranslator 
inputTranslator) {
     this.jsonBuilder = jsonBuilder;
+    this.inputTranslator = inputTranslator;
+  }
+
+  /**
+   * Transforms a RexNode tree defined in a map (from a JSON) into a RexNode,
+   * applying a special method to inputs instead of transforming them into 
inputRef.
+   * @param cluster The optimization environment
+   * @param apply is a InputTranslator lambda that transforms the map 
representing input
+   *               references into a RexNode
+   * @param o the map derived from a RexNode transformed into a JSON
+   * @return the transformed RexNode
+   */
+  public static RexNode readExpression(

Review comment:
       Let's move this method a bit further down the file. It's not the most 
important method in this class.
   
   The description 'Transforms a RexNode tree' is a bit misleading, given that 
the input is JSON not RexNode. Maybe something like 'Converts a JSON 
expression...'?
   
   Convert the anonymous inner class that implements RelInput into a private 
static inner class. That gives us an opportunity to document it. Also it will 
make it easier to refactor in future.

##########
File path: core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
##########
@@ -706,6 +717,51 @@
             + "    LogicalTableScan(table=[[hr, emps]])\n"));
   }
 
+  @Test void testJsonToRex() throws JsonProcessingException {
+    // Test simple literal without inputs
+    final String jsonString1 = "{\n"
+        + "            \"literal\": 10,\n"
+        + "            \"type\": {\n"
+        + "              \"type\": \"INTEGER\",\n"
+        + "              \"nullable\": false\n"
+        + "            }\n"
+        + "          }\n";
+
+    assertReadRex(jsonString1, "10");
+
+    // Test Binary with an input
+    final String jsonString2 = "{ \"op\": \n"
+        + "      { \"name\": \"+\",\n"
+        + "        \"kind\": \"PLUS\",\n"
+        + "        \"syntax\": \"BINARY\"\n"
+        + "      },\n"
+        + "      \"operands\": [\n"
+        + "        {\n"
+        + "          \"input\": 1,\n"
+        + "          \"sql\": \"column + 1\"\n"
+        + "        },\n"
+        + "        {\n"
+        + "          \"literal\": 1,\n"
+        + "          \"type\": { \"type\": \"INTEGER\", \"nullable\": false 
}\n"
+        + "        }\n"
+        + "      ]\n"
+        + "    }";
+    assertReadRex(jsonString2, "+(1, 1)");
+  }
+
+  private void assertReadRex(String jsonString1, String expected)

Review comment:
       better name would be `assertThatReadExpressionResult`
   
   change parameter to from `String` to `Matcher<String>`. then there will be 
an `is` at the call site, and the code will read somewhat like English (per 
junit best practices, e.g. `assertThat(1 + 2, is(3));`

##########
File path: core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
##########
@@ -429,6 +435,11 @@
     return Stream.of(SqlExplainFormat.TEXT, SqlExplainFormat.DOT);
   }
 
+  private static RexNode apply(Map<String, Object> map, RexBuilder rexBuilder, 
List<RelNode> inputs) {

Review comment:
       need better name than `apply`. Also a bit of javadoc describing intend. 
In the javadoc I'd mention that it is intended to implement the translator 
interface.




-- 
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.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to