/** * Creates a call to the CAST operator, expanding if possible. * * @param type Type to cast to * @param exp Expression being cast * @return Call to CAST operator */ public RexNode makeCast(RelDataType type, RexNode exp) { final SqlTypeName sqlType = type.getSqlTypeName(); if (exp instanceof RexLiteral) { RexLiteral literal = (RexLiteral) exp; Comparable value = literal.getValue(); if (RexLiteral.valueMatchesType(value, sqlType, false) && (!(value instanceof NlsString) || (type.getPrecision() >= ((NlsString) value).getValue().length())) && (!(value instanceof ByteString) || (type.getPrecision() >= ((ByteString) value).length()))) { switch (literal.getTypeName()) { case CHAR: if (value instanceof NlsString) { value = ((NlsString) value).rtrim(); } break; case TIMESTAMP: case TIME: final Calendar calendar = (Calendar) value; int scale = type.getScale(); if (scale == RelDataType.SCALE_NOT_SPECIFIED) { scale = 0; } calendar.setTimeInMillis( SqlFunctions.round( calendar.getTimeInMillis(), DateTimeUtils.powerX(10, 3 - scale))); break; case INTERVAL_DAY_TIME: BigDecimal value2 = (BigDecimal) value; final long multiplier = literal.getType().getIntervalQualifier().getStartUnit().multiplier; SqlTypeName typeName = type.getSqlTypeName(); // Not all types are allowed for literals switch (typeName) { case INTEGER: typeName = SqlTypeName.BIGINT; } return makeLiteral( value2.divide(BigDecimal.valueOf(multiplier), 0, BigDecimal.ROUND_HALF_DOWN), type, typeName); } return makeLiteral(value, type, literal.getTypeName()); } } else if (SqlTypeUtil.isInterval(type) && SqlTypeUtil.isExactNumeric(exp.getType())) { return makeCastExactToInterval(type, exp); } else if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.isInterval(exp.getType())) { return makeCastIntervalToExact(type, exp); } else if (sqlType == SqlTypeName.BOOLEAN && SqlTypeUtil.isExactNumeric(exp.getType())) { return makeCastExactToBoolean(type, exp); } else if (exp.getType().getSqlTypeName() == SqlTypeName.BOOLEAN && SqlTypeUtil.isExactNumeric(type)) { return makeCastBooleanToExact(type, exp); } return makeAbstractCast(type, exp); }
/** * Retrieves an interval or decimal node's integer representation * * @param node the interval or decimal value as an opaque type * @return an integer representation of the decimal value */ public RexNode decodeIntervalOrDecimal(RexNode node) { assert SqlTypeUtil.isDecimal(node.getType()) || SqlTypeUtil.isInterval(node.getType()); RelDataType bigintType = typeFactory.createSqlType(SqlTypeName.BIGINT); return makeReinterpretCast(matchNullability(bigintType, node), node, makeLiteral(false)); }