in core/src/main/java/org/apache/calcite/sql/type/SqlTypeCoercionRule.java [101:368]
static {
// We use coerceRules when we're casting
final SqlTypeMappingRules.Builder coerceRules = SqlTypeMappingRules.builder();
coerceRules.addAll(SqlTypeAssignmentRule.instance().getTypeMapping());
final Set<SqlTypeName> rule = new HashSet<>();
// Make numbers symmetrical,
// and make VARCHAR, CHAR, and TIMESTAMP castable to/from numbers
rule.add(SqlTypeName.TINYINT);
rule.add(SqlTypeName.SMALLINT);
rule.add(SqlTypeName.INTEGER);
rule.add(SqlTypeName.BIGINT);
rule.add(SqlTypeName.DECIMAL);
rule.add(SqlTypeName.FLOAT);
rule.add(SqlTypeName.REAL);
rule.add(SqlTypeName.DOUBLE);
rule.add(SqlTypeName.CHAR);
rule.add(SqlTypeName.VARCHAR);
rule.add(SqlTypeName.TIMESTAMP);
rule.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE);
rule.add(SqlTypeName.TIMESTAMP_TZ);
coerceRules.add(SqlTypeName.TINYINT, rule);
coerceRules.add(SqlTypeName.SMALLINT, rule);
coerceRules.add(SqlTypeName.INTEGER, rule);
coerceRules.add(SqlTypeName.BIGINT, rule);
coerceRules.add(SqlTypeName.FLOAT, rule);
coerceRules.add(SqlTypeName.REAL, rule);
coerceRules.add(SqlTypeName.DECIMAL, rule);
coerceRules.add(SqlTypeName.DOUBLE, rule);
coerceRules.add(SqlTypeName.CHAR, rule);
coerceRules.add(SqlTypeName.VARCHAR, rule);
// Exact numeric types are castable from intervals
for (SqlTypeName exactType : SqlTypeName.EXACT_TYPES) {
coerceRules.add(exactType,
coerceRules.copyValues(exactType)
.addAll(SqlTypeName.INTERVAL_TYPES)
.build());
}
// Intervals are castable from exact numeric
for (SqlTypeName typeName : SqlTypeName.INTERVAL_TYPES) {
coerceRules.add(typeName,
coerceRules.copyValues(typeName)
.add(SqlTypeName.TINYINT)
.add(SqlTypeName.SMALLINT)
.add(SqlTypeName.INTEGER)
.add(SqlTypeName.BIGINT)
.add(SqlTypeName.DECIMAL)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.build());
}
// BINARY is castable from VARBINARY, CHARACTERS.
coerceRules.add(SqlTypeName.BINARY,
coerceRules.copyValues(SqlTypeName.BINARY)
.add(SqlTypeName.VARBINARY)
.addAll(SqlTypeName.CHAR_TYPES)
.add(SqlTypeName.UUID)
.build());
// VARBINARY is castable from BINARY, CHARACTERS.
coerceRules.add(SqlTypeName.VARBINARY,
coerceRules.copyValues(SqlTypeName.VARBINARY)
.add(SqlTypeName.BINARY)
.addAll(SqlTypeName.CHAR_TYPES)
.add(SqlTypeName.UUID)
.build());
// VARCHAR is castable from BOOLEAN, DATE, TIME, TIMESTAMP, numeric types, binary, uuid, and
// intervals
coerceRules.add(SqlTypeName.VARCHAR,
coerceRules.copyValues(SqlTypeName.VARCHAR)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.BOOLEAN)
.add(SqlTypeName.DATE)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.addAll(SqlTypeName.BINARY_TYPES)
.addAll(SqlTypeName.NUMERIC_TYPES)
.addAll(SqlTypeName.INTERVAL_TYPES)
.add(SqlTypeName.UUID)
.build());
// CHAR is castable from BOOLEAN, DATE, TIME, TIMESTAMP, numeric types, binary, uuid, and
// intervals
coerceRules.add(SqlTypeName.CHAR,
coerceRules.copyValues(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.add(SqlTypeName.BOOLEAN)
.add(SqlTypeName.DATE)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.addAll(SqlTypeName.BINARY_TYPES)
.addAll(SqlTypeName.NUMERIC_TYPES)
.addAll(SqlTypeName.INTERVAL_TYPES)
.add(SqlTypeName.UUID)
.build());
// BOOLEAN is castable from ...
coerceRules.add(SqlTypeName.BOOLEAN,
coerceRules.copyValues(SqlTypeName.BOOLEAN)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.NUMERIC_TYPES)
.build());
// UUID is castable from ...
coerceRules.add(SqlTypeName.UUID,
coerceRules.copyValues(SqlTypeName.UUID)
.add(SqlTypeName.VARCHAR)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.BINARY)
.add(SqlTypeName.VARBINARY)
.build());
// DATE, TIME, and TIMESTAMP are castable from
// CHAR and VARCHAR.
// DATE is castable from...
coerceRules.add(SqlTypeName.DATE,
coerceRules.copyValues(SqlTypeName.DATE)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.build());
// TIME is castable from...
coerceRules.add(SqlTypeName.TIME,
coerceRules.copyValues(SqlTypeName.TIME)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.build());
// TIME WITH LOCAL TIME ZONE is castable from...
coerceRules.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE,
coerceRules.copyValues(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.build());
// TIME WITH TIME ZONE is castable from...
coerceRules.add(SqlTypeName.TIME_TZ,
coerceRules.copyValues(SqlTypeName.TIME_TZ)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.build());
// TIMESTAMP is castable from...
coerceRules.add(SqlTypeName.TIMESTAMP,
coerceRules.copyValues(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.DATE)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.addAll(SqlTypeName.NUMERIC_TYPES)
.build());
// TIMESTAMP WITH LOCAL TIME ZONE is castable from...
coerceRules.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE,
coerceRules.copyValues(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.DATE)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.addAll(SqlTypeName.NUMERIC_TYPES)
.build());
// TIMESTAMP WITH TIME ZONE is castable from...
coerceRules.add(SqlTypeName.TIMESTAMP_TZ,
coerceRules.copyValues(SqlTypeName.TIMESTAMP_TZ)
.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIMESTAMP)
.add(SqlTypeName.DATE)
.add(SqlTypeName.TIME)
.add(SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE)
.add(SqlTypeName.TIME_TZ)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.addAll(SqlTypeName.BINARY_TYPES)
.addAll(SqlTypeName.NUMERIC_TYPES)
.build());
// GEOMETRY is castable from ...
coerceRules.add(SqlTypeName.GEOMETRY,
coerceRules.copyValues(SqlTypeName.GEOMETRY)
.addAll(SqlTypeName.CHAR_TYPES)
.build());
INSTANCE = new SqlTypeCoercionRule(coerceRules.map);
// Lenient casting allowing casting between BOOLEAN and numbers.
rule.clear();
rule.add(SqlTypeName.TINYINT);
rule.add(SqlTypeName.SMALLINT);
rule.add(SqlTypeName.INTEGER);
rule.add(SqlTypeName.BIGINT);
rule.add(SqlTypeName.DECIMAL);
rule.add(SqlTypeName.FLOAT);
rule.add(SqlTypeName.REAL);
rule.add(SqlTypeName.DOUBLE);
rule.add(SqlTypeName.CHAR);
rule.add(SqlTypeName.VARCHAR);
rule.add(SqlTypeName.BOOLEAN);
rule.add(SqlTypeName.TIMESTAMP);
rule.add(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE);
rule.add(SqlTypeName.TIMESTAMP_TZ);
coerceRules.add(SqlTypeName.TINYINT, rule);
coerceRules.add(SqlTypeName.SMALLINT, rule);
coerceRules.add(SqlTypeName.INTEGER, rule);
coerceRules.add(SqlTypeName.BIGINT, rule);
// Lenient casting allowing ARRAY to be casted from CHAR and VARCHAR.
coerceRules.add(SqlTypeName.ARRAY,
coerceRules.copyValues(SqlTypeName.ARRAY)
.add(SqlTypeName.CHAR)
.add(SqlTypeName.VARCHAR)
.build());
LENIENT_INSTANCE = new SqlTypeCoercionRule(coerceRules.map);
THREAD_PROVIDERS = TryThreadLocal.of(SqlTypeCoercionRule.INSTANCE);
}