/** Ensures that a type's nullability matches a value's nullability. */ public RelDataType matchNullability(RelDataType type, RexNode value) { boolean typeNullability = type.isNullable(); boolean valueNullability = value.getType().isNullable(); if (typeNullability != valueNullability) { return getTypeFactory().createTypeWithNullability(type, valueNullability); } return type; }
/** * Makes an expression which converts a value of type T to a value of type T NOT NULL, or throws * if the value is NULL. If the expression is already NOT NULL, does nothing. */ public RexNode makeNotNullCast(RexNode expr) { RelDataType type = expr.getType(); if (!type.isNullable()) { return expr; } RelDataType typeNotNull = getTypeFactory().createTypeWithNullability(type, false); return new RexCall(typeNotNull, SqlStdOperatorTable.CAST, ImmutableList.of(expr)); }
public Type getJavaClass(RelDataType type) { if (type instanceof JavaType) { JavaType javaType = (JavaType) type; return javaType.getJavaClass(); } if (type.isStruct() && type.getFieldCount() == 1) { return getJavaClass(type.getFieldList().get(0).getType()); } if (type instanceof BasicSqlType || type instanceof IntervalSqlType) { switch (type.getSqlTypeName()) { case VARCHAR: case CHAR: return String.class; case DATE: case TIME: case INTEGER: case INTERVAL_YEAR_MONTH: return type.isNullable() ? Integer.class : int.class; case TIMESTAMP: case BIGINT: case INTERVAL_DAY_TIME: return type.isNullable() ? Long.class : long.class; case SMALLINT: return type.isNullable() ? Short.class : short.class; case TINYINT: return type.isNullable() ? Byte.class : byte.class; case DECIMAL: return BigDecimal.class; case BOOLEAN: return type.isNullable() ? Boolean.class : boolean.class; case DOUBLE: case FLOAT: // sic return type.isNullable() ? Double.class : double.class; case REAL: return type.isNullable() ? Float.class : float.class; case BINARY: case VARBINARY: return ByteString.class; case ARRAY: return Array.class; case ANY: return Object.class; } } switch (type.getSqlTypeName()) { case ROW: assert type instanceof RelRecordType; if (type instanceof JavaRecordType) { return ((JavaRecordType) type).clazz; } else { return createSyntheticType((RelRecordType) type); } case MAP: return Map.class; case ARRAY: case MULTISET: return List.class; } return null; }
public RelDataType toSql(RelDataType type) { if (type instanceof RelRecordType) { return createStructType( Lists.transform( type.getFieldList(), new Function<RelDataTypeField, RelDataType>() { public RelDataType apply(RelDataTypeField a0) { return toSql(a0.getType()); } }), type.getFieldNames()); } if (type instanceof JavaType) { return createTypeWithNullability(createSqlType(type.getSqlTypeName()), type.isNullable()); } return type; }
/** * Creates a literal of a given type. The value is assumed to be compatible with the type. * * @param value Value * @param type Type * @param allowCast Whether to allow a cast. If false, value is always a {@link RexLiteral} but * may not be the exact type * @return Simple literal, or cast simple literal */ public RexNode makeLiteral(Object value, RelDataType type, boolean allowCast) { if (value == null) { return makeCast(type, constantNull); } if (type.isNullable()) { final RelDataType typeNotNull = typeFactory.createTypeWithNullability(type, false); RexNode literalNotNull = makeLiteral(value, typeNotNull, allowCast); return makeAbstractCast(type, literalNotNull); } value = clean(value, type); RexLiteral literal; final List<RexNode> operands; switch (type.getSqlTypeName()) { case CHAR: return makeCharLiteral(padRight((NlsString) value, type.getPrecision())); case VARCHAR: literal = makeCharLiteral((NlsString) value); if (allowCast) { return makeCast(type, literal); } else { return literal; } case BINARY: return makeBinaryLiteral(padRight((ByteString) value, type.getPrecision())); case VARBINARY: literal = makeBinaryLiteral((ByteString) value); if (allowCast) { return makeCast(type, literal); } else { return literal; } case TINYINT: case SMALLINT: case INTEGER: case BIGINT: case DECIMAL: return makeExactLiteral((BigDecimal) value, type); case FLOAT: case REAL: case DOUBLE: return makeApproxLiteral((BigDecimal) value, type); case BOOLEAN: return (Boolean) value ? booleanTrue : booleanFalse; case TIME: return makeTimeLiteral((Calendar) value, type.getPrecision()); case DATE: return makeDateLiteral((Calendar) value); case TIMESTAMP: return makeTimestampLiteral((Calendar) value, type.getPrecision()); case INTERVAL_YEAR_MONTH: case INTERVAL_DAY_TIME: return makeIntervalLiteral((BigDecimal) value, type.getIntervalQualifier()); case MAP: final MapSqlType mapType = (MapSqlType) type; @SuppressWarnings("unchecked") final Map<Object, Object> map = (Map) value; operands = new ArrayList<RexNode>(); for (Map.Entry<Object, Object> entry : map.entrySet()) { operands.add(makeLiteral(entry.getKey(), mapType.getKeyType(), allowCast)); operands.add(makeLiteral(entry.getValue(), mapType.getValueType(), allowCast)); } return makeCall(SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, operands); case ARRAY: final ArraySqlType arrayType = (ArraySqlType) type; @SuppressWarnings("unchecked") final List<Object> listValue = (List) value; operands = new ArrayList<RexNode>(); for (Object entry : listValue) { operands.add(makeLiteral(entry, arrayType.getComponentType(), allowCast)); } return makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR, operands); case ANY: return makeLiteral(value, guessType(value), allowCast); default: throw Util.unexpected(type.getSqlTypeName()); } }
/** * Creates a reference to all the fields in the row. * * <p>For example, if the input row has type <code>T{f0,f1,f2,f3,f4}</code> then <code> * makeRangeReference(T{f0,f1,f2,f3,f4}, S{f3,f4}, 3)</code> is an expression which yields the * last 2 fields. * * @param type Type of the resulting range record. * @param offset Index of first field. * @param nullable Whether the record is nullable. */ public RexRangeRef makeRangeReference(RelDataType type, int offset, boolean nullable) { if (nullable && !type.isNullable()) { type = typeFactory.createTypeWithNullability(type, nullable); } return new RexRangeRef(type, offset); }