in modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java [755:885]
RexNode toRex(RelInput relInput, Object o) {
RelOptCluster cluster = relInput.getCluster();
RexBuilder rexBuilder = cluster.getRexBuilder();
if (o == null) {
return null;
} else if (o instanceof Map) {
Map map = (Map) o;
Map<String, Object> opMap = (Map) map.get("op");
IgniteTypeFactory typeFactory = Commons.typeFactory(cluster);
if (opMap != null) {
if (map.containsKey("class")) {
opMap.put("class", map.get("class"));
}
List operands = (List) map.get("operands");
List<RexNode> rexOperands = toRexList(relInput, operands);
Object jsonType = map.get("type");
Map window = (Map) map.get("window");
if (window != null) {
final SqlAggFunction operator = (SqlAggFunction) toOp(opMap);
final RelDataType type = toType(typeFactory, jsonType);
final List<RexNode> partitionKeys = window.containsKey("partition")
? toRexList(relInput, (List) window.get("partition")) : new ArrayList<>();
List<RexFieldCollation> orderKeys = new ArrayList<>();
if (window.containsKey("order")) {
orderKeys = toRexFieldCollationList(relInput, (List) window.get("order"));
}
RexWindowBound lowerBound;
RexWindowBound upperBound;
boolean physical;
if (window.get("rows-lower") != null) {
lowerBound = toRexWindowBound(relInput, (Map) window.get("rows-lower"));
upperBound = toRexWindowBound(relInput, (Map) window.get("rows-upper"));
physical = true;
} else if (window.get("range-lower") != null) {
lowerBound = toRexWindowBound(relInput, (Map) window.get("range-lower"));
upperBound = toRexWindowBound(relInput, (Map) window.get("range-upper"));
physical = false;
} else {
// No ROWS or RANGE clause
lowerBound = null;
upperBound = null;
physical = false;
}
boolean distinct = (Boolean) map.get("distinct");
return rexBuilder.makeOver(type, operator, rexOperands, partitionKeys,
ImmutableList.copyOf(orderKeys), lowerBound, upperBound, physical,
true, false, distinct, false);
} else {
SqlOperator operator = toOp(opMap);
RelDataType type;
if (jsonType != null) {
type = toType(typeFactory, jsonType);
} else {
type = rexBuilder.deriveReturnType(operator, rexOperands);
}
return rexBuilder.makeCall(type, operator, rexOperands);
}
}
Integer input = (Integer) map.get("input");
if (input != null) {
// Check if it is a local ref.
if (map.containsKey("type")) {
RelDataType type = toType(typeFactory, map.get("type"));
return map.get("dynamic") == Boolean.TRUE
? rexBuilder.makeDynamicParam(type, input)
: rexBuilder.makeLocalRef(type, input);
}
List<RelNode> inputNodes = relInput.getInputs();
int i = input;
for (RelNode inputNode : inputNodes) {
RelDataType rowType = inputNode.getRowType();
if (i < rowType.getFieldCount()) {
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");
}
String field = (String) map.get("field");
if (field != null) {
Object jsonExpr = map.get("expr");
RexNode expr = toRex(relInput, jsonExpr);
return rexBuilder.makeFieldAccess(expr, field, true);
}
String correl = (String) map.get("correl");
if (correl != null) {
RelDataType type = toType(typeFactory, map.get("type"));
return rexBuilder.makeCorrel(type, new CorrelationId(correl));
}
if (map.containsKey("literal")) {
Object literal = map.get("literal");
RelDataType type = toType(typeFactory, map.get("type"));
if (literal == null) {
return rexBuilder.makeNullLiteral(type);
}
if (type.getSqlTypeName() == SqlTypeName.SYMBOL) {
literal = toEnum(literal);
} else if (type.getSqlTypeName().getFamily() == SqlTypeFamily.BINARY) {
literal = toByteString(literal);
} else if (type.getSqlTypeName().getFamily() == SqlTypeFamily.TIMESTAMP && literal instanceof Integer) {
literal = ((Integer) literal).longValue();
}
return rexBuilder.makeLiteral(literal, type, true);
}
throw new UnsupportedOperationException("cannot convert to rex " + o);
} else if (o instanceof Boolean) {
return rexBuilder.makeLiteral((Boolean) o);
} else if (o instanceof String) {
return rexBuilder.makeLiteral((String) o);
} else if (o instanceof Number) {
Number number = (Number) o;
if (number instanceof Double || number instanceof Float) {
return rexBuilder.makeApproxLiteral(
BigDecimal.valueOf(number.doubleValue()));
} else {
return rexBuilder.makeExactLiteral(
BigDecimal.valueOf(number.longValue()));
}
} else {
throw new UnsupportedOperationException("cannot convert to rex " + o);
}
}