public static VoltType determineImplicitCasting(VoltType left, VoltType right) {
//
// Make sure both are valid
//
if (left == VoltType.INVALID || right == VoltType.INVALID) {
throw new VoltTypeException("ERROR: Unable to determine cast type for '" + left + "' and '" + right + "' types");
}
// Check for NULL first, if either type is NULL the output is always NULL
// XXX do we need to actually check for all NULL_foo types here?
else if (left == VoltType.NULL || right == VoltType.NULL)
{
return VoltType.NULL;
}
//
// No mixing of strings and numbers
//
else if ((left == VoltType.STRING && right != VoltType.STRING) ||
(left != VoltType.STRING && right == VoltType.STRING))
{
throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
left + "' and '" + right + "' types");
}
// Allow promoting INTEGER types to DECIMAL.
else if ((left == VoltType.DECIMAL || right == VoltType.DECIMAL) &&
!(left.isExactNumeric() && right.isExactNumeric()))
{
throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
left + "' and '" + right + "' types");
}
//
// The following list contains the rules that use for casting:
//
// (1) If both types are a STRING, the output is always a STRING
// Note that up above we made sure that they do not mix strings and numbers
// Example: STRING + STRING -> STRING
// (2) If one type is a DECIMAL, the output is always a DECIMAL
// Note that above we made sure that DECIMAL only mixes with
// allowed types
// (3) Floating-point types take precedence over integers
// Example: FLOAT + INTEGER -> FLOAT
// (4) Specific types for floating-point and integer types take precedence
// over the more general types
// Example: MONEY + FLOAT -> MONEY
// Example: TIMESTAMP + INTEGER -> TIMESTAMP
VoltType cast_order[] = { VoltType.STRING,
VoltType.DECIMAL,
VoltType.FLOAT,
VoltType.TIMESTAMP,
VoltType.BIGINT };
for (VoltType cast_type : cast_order) {
//
// If any one of the types is the current cast type, we'll use that
//
if (left == cast_type || right == cast_type)
{
return cast_type;
}
}
// If we have INT types smaller than BIGINT
// promote the output up to BIGINT
if ((left == VoltType.INTEGER || left == VoltType.SMALLINT || left == VoltType.TINYINT) &&
(right == VoltType.INTEGER || right == VoltType.SMALLINT || right == VoltType.TINYINT))
{
return VoltType.BIGINT;
}
// If we get here, we couldn't figure out what to do
throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
left + "' and '" + right + "' types");
}