/** * @see TypeCompiler#resolveArithmeticOperation * @exception StandardException Thrown on error */ public DataTypeDescriptor resolveArithmeticOperation( DataTypeDescriptor leftType, DataTypeDescriptor rightType, String operator) throws StandardException { NumericTypeCompiler higherTC; DataTypeDescriptor higherType; boolean nullable; int precision, scale, maximumWidth; /* ** Check the right type to be sure it's a number. By convention, ** we call this method off the TypeId of the left operand, so if ** we get here, we know the left operand is a number. */ if (SanityManager.DEBUG) SanityManager.ASSERT( leftType.getTypeId().isNumericTypeId(), "The left type is supposed to be a number because we're resolving an arithmetic operator"); TypeId leftTypeId = leftType.getTypeId(); TypeId rightTypeId = rightType.getTypeId(); boolean supported = true; if (!(rightTypeId.isNumericTypeId())) { supported = false; } if (TypeCompiler.MOD_OP.equals(operator)) { switch (leftTypeId.getJDBCTypeId()) { case java.sql.Types.TINYINT: case java.sql.Types.SMALLINT: case java.sql.Types.INTEGER: case java.sql.Types.BIGINT: break; default: supported = false; break; } switch (rightTypeId.getJDBCTypeId()) { case java.sql.Types.TINYINT: case java.sql.Types.SMALLINT: case java.sql.Types.INTEGER: case java.sql.Types.BIGINT: break; default: supported = false; break; } } if (!supported) { throw StandardException.newException( SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, operator, leftType.getTypeId().getSQLTypeName(), rightType.getTypeId().getSQLTypeName()); } /* ** Take left as the higher precedence if equal */ if (rightTypeId.typePrecedence() > leftTypeId.typePrecedence()) { higherType = rightType; higherTC = (NumericTypeCompiler) getTypeCompiler(rightTypeId); } else { higherType = leftType; higherTC = (NumericTypeCompiler) getTypeCompiler(leftTypeId); } /* The calculation of precision and scale should be based upon * the type with higher precedence, which is going to be the result * type, this is also to be consistent with maximumWidth. Beetle 3906. */ precision = higherTC.getPrecision(operator, leftType, rightType); scale = higherTC.getScale(operator, leftType, rightType); if (higherType.getTypeId().isDecimalTypeId()) { maximumWidth = (scale > 0) ? precision + 3 : precision + 1; /* ** Be careful not to overflow */ if (maximumWidth < precision) { maximumWidth = Integer.MAX_VALUE; } } else { maximumWidth = higherType.getMaximumWidth(); } /* The result is nullable if either side is nullable */ nullable = leftType.isNullable() || rightType.isNullable(); /* ** The higher type does not have the right nullability. Create a ** new DataTypeDescriptor that has the correct type and nullability. ** ** It's OK to call the implementation of the DataTypeDescriptorFactory ** here, because we're in the same package. */ return new DataTypeDescriptor(higherType.getTypeId(), precision, scale, nullable, maximumWidth); }