soumyakanti3578 commented on code in PR #5131: URL: https://github.com/apache/hive/pull/5131#discussion_r1581351989
########## ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveRelJson.java: ########## @@ -43,9 +127,170 @@ public Object toJson(Object value) { if (value instanceof RelDistribution) { return toJson((RelDistribution) value); } + if (value instanceof RexNode) { + return toJson((RexNode) value); + } + if (value instanceof RelDataTypeField) { + return toJson((RelDataTypeField) value); + } + if (value instanceof RelDataType) { + return toJson((RelDataType) value); + } + if (value instanceof AggregateCall) { + return toJson((AggregateCall) value); + } + if (value instanceof HiveTableScan.HiveTableScanTrait) { + return ((HiveTableScan.HiveTableScanTrait) value).name(); + } return super.toJson(value); } + @Override + public Object toJson(AggregateCall node) { + final Map<String, Object> map = (Map<String, Object>) super.toJson(node); + map.put("type", toJson(node.getType())); + if (node.getCollation() != RelCollations.EMPTY) { + map.put("collation", toJson(node.getCollation())); + } + return map; + } + + private Object toJson(RelDataTypeField node) { + final Map<String, Object> map; + if (node.getType().isStruct()) { + map = jsonBuilder.map(); + map.put("fields", toJson(node.getType())); + } else { + map = (Map<String, Object>) toJson(node.getType()); + } + map.put("name", node.getName()); + return map; + } + + private Object toJson(RelDataType node) { + if (node.isStruct()) { + final List<Object> list = jsonBuilder.list(); + for (RelDataTypeField field : node.getFieldList()) { + list.add(toJson(field)); + } + return list; + } else { + final Map<String, Object> map = jsonBuilder.map(); + map.put("type", node.getSqlTypeName().name()); + map.put(NULLABLE, node.isNullable()); + if (node.getSqlTypeName().allowsPrec()) { + map.put("precision", node.getPrecision()); + } + if (node.getSqlTypeName().allowsScale()) { + map.put("scale", node.getScale()); + } + + if (SqlTypeName.MAP == node.getSqlTypeName()) { + map.put("key", toJson(node.getKeyType())); + map.put("value", toJson(node.getValueType())); + } else if (SqlTypeName.ARRAY == node.getSqlTypeName()) { + map.put("component", toJson(node.getComponentType())); + } + return map; + } + } + + private Object toJson(RexNode node) { + final Map<String, Object> map; + switch (node.getKind()) { + case FIELD_ACCESS: + map = jsonBuilder.map(); + final RexFieldAccess fieldAccess = (RexFieldAccess) node; + map.put("field", fieldAccess.getField().getName()); + map.put("expr", toJson(fieldAccess.getReferenceExpr())); + return map; + case LITERAL: + return toJsonLiteral((RexLiteral) node); + case INPUT_REF: + case LOCAL_REF: + map = jsonBuilder.map(); + map.put("input", ((RexSlot) node).getIndex()); + map.put("name", ((RexSlot) node).getName()); + map.put("type", toJson(node.getType())); + return map; + case CORREL_VARIABLE: + map = jsonBuilder.map(); + map.put("correl", ((RexCorrelVariable) node).getName()); + map.put("type", toJson(node.getType())); + return map; + case DYNAMIC_PARAM: + map = jsonBuilder.map(); + map.put("dynamic_param", true); + map.put("index", ((RexDynamicParam) node).getIndex()); + return map; + default: + Map<String, Object> mapRexCall = toJsonRexCall(node); + if (mapRexCall != null) { + return mapRexCall; + } + throw new UnsupportedOperationException("unknown rex " + node); + } + } + + @Nullable + private Map<String, Object> toJsonRexCall(RexNode node) { + Map<String, Object> map = null; + if (node instanceof RexCall) { + final RexCall call = (RexCall) node; + map = jsonBuilder.map(); + map.put("op", toJson(call.getOperator())); + map.put("type", toJson(call.getType())); + final List<Object> list = jsonBuilder.list(); + for (RexNode operand : call.getOperands()) { + list.add(toJson(operand)); + } + map.put(OPERANDS, list); + switch (node.getKind()) { + case CAST: + case MAP_QUERY_CONSTRUCTOR: + case MAP_VALUE_CONSTRUCTOR: + case ARRAY_QUERY_CONSTRUCTOR: + case ARRAY_VALUE_CONSTRUCTOR: + map.put("type", toJson(node.getType())); + break; + default: + break; + } + if (call.getOperator() instanceof SqlFunction && + (((SqlFunction) call.getOperator()).getFunctionType().isUserDefined())) { + SqlOperator op = call.getOperator(); + map.put("class", op.getClass().getName()); + map.put("type", toJson(node.getType())); + map.put("deterministic", op.isDeterministic()); + map.put("dynamic", op.isDynamicFunction()); + } + if (call instanceof RexOver) { + RexOver over = (RexOver) call; + map.put(DISTINCT, over.isDistinct()); + map.put("type", toJson(node.getType())); + map.put("window", toJson(over.getWindow())); + map.put("ignoreNulls", toJson(over.ignoreNulls())); + } + } + return map; + } + + @NotNull + private Map<String, Object> toJsonLiteral(RexLiteral literal) { + final Map<String, Object> map; + map = jsonBuilder.map(); + final Object value; + if (SqlTypeFamily.TIMESTAMP == literal.getTypeName().getFamily()) { + // Had to do this to prevent millis or nanos from getting trimmed + value = literal.computeDigest(RexDigestIncludeType.NO_TYPE); + } else { + value = literal.getValue3(); + } + map.put(LITERAL, RelEnumTypes.fromEnum(value)); + map.put("type", toJson(literal.getType())); + return map; + } Review Comment: I have tried to use the Calcite code as much as possible, and only had to copy these when I needed to add something extra to the method or a part of the method and the super method is private (and thus not override-able). For example in this case, for TIMESTAMPs I needed to handle it differently than what was implemented in Calcite. Also you can see that `toJsonRexCall` has extra things like [adding type to RexCalls](https://github.com/apache/hive/pull/5131/commits/ed787c28ba0708d04385fab5588296e1f1638284), support for MAPs and ARRAYs which is missing in the super method, etc. These are needed in the serialized plan to get all the information we need to deserialize it. To see an example of where I was able to reuse super method, please checkout [this patch for AggregateCalls](https://github.com/apache/hive/pull/5131/commits/c82de5698e6a1b9c029a31034444d1991f0a0701#diff-29a8fea85c2750c60547a7b4d3088d3f704a48f77f6a6b9eb933f1b5b527e033R78). -- 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: gitbox-unsubscr...@hive.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: gitbox-unsubscr...@hive.apache.org For additional commands, e-mail: gitbox-h...@hive.apache.org