private RexNode makeCastExactToInterval(RelDataType toType, RexNode exp) { IntervalSqlType intervalType = (IntervalSqlType) toType; TimeUnit endUnit = intervalType.getIntervalQualifier().getEndUnit(); if (endUnit == null) { endUnit = intervalType.getIntervalQualifier().getStartUnit(); } int scale = 0; if (endUnit == TimeUnit.SECOND) { scale = Math.min( intervalType .getIntervalQualifier() .getFractionalSecondPrecision(typeFactory.getTypeSystem()), 3); } BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier).divide(BigDecimal.TEN.pow(scale)); RelDataType decimalType = getTypeFactory() .createSqlType(SqlTypeName.DECIMAL, scale + intervalType.getPrecision(), scale); RexNode value = decodeIntervalOrDecimal(ensureType(decimalType, exp, true)); if (multiplier.longValue() != 1) { value = makeCall(SqlStdOperatorTable.MULTIPLY, value, makeExactLiteral(multiplier)); } return encodeIntervalOrDecimal(value, toType, false); }
/** * Returns the type the row which results when two relations are joined. * * <p>The resulting row type consists of the system fields (if any), followed by the fields of the * left type, followed by the fields of the right type. The field name list, if present, overrides * the original names of the fields. * * @param typeFactory Type factory * @param leftType Type of left input to join * @param rightType Type of right input to join * @param fieldNameList If not null, overrides the original names of the fields * @param systemFieldList List of system fields that will be prefixed to output row type; * typically empty but must not be null * @return type of row which results when two relations are joined */ public static RelDataType createJoinType( RelDataTypeFactory typeFactory, RelDataType leftType, RelDataType rightType, List<String> fieldNameList, List<RelDataTypeField> systemFieldList) { assert (fieldNameList == null) || (fieldNameList.size() == (systemFieldList.size() + leftType.getFieldCount() + rightType.getFieldCount())); List<String> nameList = new ArrayList<>(); final List<RelDataType> typeList = new ArrayList<>(); // Use a set to keep track of the field names; this is needed // to ensure that the contains() call to check for name uniqueness // runs in constant time; otherwise, if the number of fields is large, // doing a contains() on a list can be expensive. final Set<String> uniqueNameList = typeFactory.getTypeSystem().isSchemaCaseSensitive() ? new HashSet<String>() : new TreeSet<>(String.CASE_INSENSITIVE_ORDER); addFields(systemFieldList, typeList, nameList, uniqueNameList); addFields(leftType.getFieldList(), typeList, nameList, uniqueNameList); if (rightType != null) { addFields(rightType.getFieldList(), typeList, nameList, uniqueNameList); } if (fieldNameList != null) { assert fieldNameList.size() == nameList.size(); nameList = fieldNameList; } return typeFactory.createStructType(typeList, nameList); }
/** Creates a numeric literal. */ public RexLiteral makeExactLiteral(BigDecimal bd) { RelDataType relType; int scale = bd.scale(); long l = bd.unscaledValue().longValue(); assert scale >= 0; assert scale <= typeFactory.getTypeSystem().getMaxNumericScale() : scale; assert BigDecimal.valueOf(l, scale).equals(bd); if (scale == 0) { if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) { relType = typeFactory.createSqlType(SqlTypeName.INTEGER); } else { relType = typeFactory.createSqlType(SqlTypeName.BIGINT); } } else { int precision = bd.unscaledValue().toString().length(); relType = typeFactory.createSqlType(SqlTypeName.DECIMAL, scale, precision); } return makeExactLiteral(bd, relType); }