RexNode toRex()

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);
        }
    }