in src/main/java/com/microsoft/sqlserver/jdbc/Column.java [200:374]
void updateValue(JDBCType jdbcType, Object value, JavaType javaType, StreamSetterArgs streamSetterArgs,
Calendar cal, Integer scale, SQLServerConnection con,
SQLServerStatementColumnEncryptionSetting stmtColumnEncriptionSetting, Integer precision,
boolean forceEncrypt, int parameterIndex) throws SQLServerException {
SSType ssType = typeInfo.getSSType();
if (null != cryptoMetadata) {
if (SSType.VARBINARYMAX == cryptoMetadata.baseTypeInfo.getSSType() && JDBCType.BINARY == jdbcType) {
jdbcType = cryptoMetadata.baseTypeInfo.getSSType().getJDBCType();
}
if (null != value) {
// for encrypted tinyint, we need to convert short value to byte value, otherwise it would be sent as
// smallint
if (JDBCType.TINYINT == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()
&& javaType == JavaType.SHORT) {
if (value instanceof Boolean) {
if ((boolean) value) {
value = 1;
} else {
value = 0;
}
}
String stringValue = "" + value;
Short shortValue = Short.valueOf(stringValue);
if (shortValue >= 0 && shortValue <= 255) {
value = shortValue.byteValue();
javaType = JavaType.BYTE;
jdbcType = JDBCType.TINYINT;
}
}
}
// if the column is encrypted and value is null, get the real column type instead of binary types
else if (jdbcType.isBinary()) {
jdbcType = cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType();
}
}
if (null == scale && null != cryptoMetadata) {
scale = cryptoMetadata.getBaseTypeInfo().getScale();
}
// if jdbcType is char or varchar, check if the column is actually char/varchar or nchar/nvarchar
// in order to make updateString() work with encrypted Nchar typpes
if (null != cryptoMetadata && (JDBCType.CHAR == jdbcType || JDBCType.VARCHAR == jdbcType)) {
if (JDBCType.NVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()
|| JDBCType.NCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()
|| JDBCType.LONGNVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()) {
jdbcType = cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType();
}
}
if (Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, con)) {
if ((null == cryptoMetadata) && forceEncrypt) {
MessageFormat form = new MessageFormat(
SQLServerException.getErrString("R_ForceEncryptionTrue_HonorAETrue_UnencryptedColumnRS"));
Object[] msgArgs = {parameterIndex};
throw new SQLServerException(null, form.format(msgArgs), null, 0, false);
} else {
setJdbcTypeSetByUser(jdbcType);
this.valueLength = Util.getValueLengthBaseOnJavaType(value, javaType, precision, scale, jdbcType);
// for update encrypted nchar or nvarchar value on result set, must double the value length,
// otherwise, the data is truncated.
if (null != cryptoMetadata) {
if (JDBCType.NCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()
|| JDBCType.NVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()
|| JDBCType.LONGNVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()) {
this.valueLength = valueLength * 2;
}
}
}
} else {
if (forceEncrypt) {
MessageFormat form = new MessageFormat(
SQLServerException.getErrString("R_ForceEncryptionTrue_HonorAEFalseRS"));
Object[] msgArgs = {parameterIndex};
throw new SQLServerException(null, form.format(msgArgs), null, 0, false);
}
}
if (null != streamSetterArgs) {
if (!streamSetterArgs.streamType.convertsTo(typeInfo))
DataTypes.throwConversionError(streamSetterArgs.streamType.toString(), ssType.toString());
} else {
if (null != cryptoMetadata) {
// For GUID, set the JDBCType before checking for conversion
if ((JDBCType.UNKNOWN == jdbcType) && (value instanceof java.util.UUID)) {
javaType = JavaType.STRING;
jdbcType = JDBCType.GUID;
setJdbcTypeSetByUser(jdbcType);
}
SSType basicSSType = cryptoMetadata.baseTypeInfo.getSSType();
if (!jdbcType.convertsTo(basicSSType))
DataTypes.throwConversionError(jdbcType.toString(), ssType.toString());
JDBCType jdbcTypeFromSSType = getJDBCTypeFromBaseSSType(basicSSType, jdbcType);
if (jdbcTypeFromSSType != jdbcType) {
setJdbcTypeSetByUser(jdbcTypeFromSSType);
jdbcType = jdbcTypeFromSSType;
this.valueLength = Util.getValueLengthBaseOnJavaType(value, javaType, precision, scale, jdbcType);
}
} else {
if (!jdbcType.convertsTo(ssType))
DataTypes.throwConversionError(jdbcType.toString(), ssType.toString());
}
}
// DateTimeOffset is not supported with SQL Server versions earlier than Katmai
if ((JDBCType.DATETIMEOFFSET == jdbcType || JavaType.DATETIMEOFFSET == javaType) && !con.isKatmaiOrLater()) {
throw new SQLServerException(SQLServerException.getErrString("R_notSupported"),
SQLState.DATA_EXCEPTION_NOT_SPECIFIC, DriverError.NOT_SET, null);
}
// sendStringParametersAsUnicode
// If set to true, this connection property tells the driver to send textual parameters
// to the server as Unicode rather than MBCS. This is accomplished here by re-tagging
// the value with the appropriate corresponding Unicode type.
if ((null != cryptoMetadata) && (con.sendStringParametersAsUnicode()) && (JavaType.STRING == javaType
|| JavaType.READER == javaType || JavaType.CLOB == javaType || JavaType.OBJECT == javaType)) {
jdbcType = getSSPAUJDBCType(jdbcType);
}
// Cheesy checks determine whether updating is allowed, but do not determine HOW to do
// the update (i.e. what JDBC type to use for the update). The JDBC type to use depends
// on the SQL Server type of the column and the JDBC type requested.
//
// In most cases the JDBCType to use is just the requested JDBCType. But in some cases
// a client side type conversion is necessary because SQL Server does not directly support
// conversion from the requested JDBCType to the column SSType, or the driver needs to
// provide special data conversion.
// Update of Unicode SSType from textual JDBCType: Use Unicode.
if ((SSType.NCHAR == ssType || SSType.NVARCHAR == ssType || SSType.NVARCHARMAX == ssType
|| SSType.NTEXT == ssType || SSType.XML == ssType) &&
(JDBCType.CHAR == jdbcType || JDBCType.VARCHAR == jdbcType || JDBCType.LONGVARCHAR == jdbcType
|| JDBCType.CLOB == jdbcType)) {
jdbcType = (JDBCType.CLOB == jdbcType) ? JDBCType.NCLOB : JDBCType.NVARCHAR;
}
// Update of binary SSType from textual JDBCType: Convert hex to binary.
else if ((SSType.BINARY == ssType || SSType.VARBINARY == ssType || SSType.VARBINARYMAX == ssType
|| SSType.IMAGE == ssType || SSType.UDT == ssType) &&
(JDBCType.CHAR == jdbcType || JDBCType.VARCHAR == jdbcType || JDBCType.LONGVARCHAR == jdbcType)) {
jdbcType = JDBCType.VARBINARY;
}
// Update of textual SSType from temporal JDBCType requires
// client-side conversion from temporal to textual.
else if ((JDBCType.TIMESTAMP == jdbcType || JDBCType.DATE == jdbcType || JDBCType.TIME == jdbcType
|| JDBCType.DATETIMEOFFSET == jdbcType) &&
(SSType.CHAR == ssType || SSType.VARCHAR == ssType || SSType.VARCHARMAX == ssType
|| SSType.TEXT == ssType || SSType.NCHAR == ssType || SSType.NVARCHAR == ssType
|| SSType.NVARCHARMAX == ssType || SSType.NTEXT == ssType)) {
jdbcType = JDBCType.NCHAR;
}
// Lazily create the updater DTV on first update of the column
if (null == updaterDTV)
updaterDTV = new DTV();
// Set the column's value
updaterDTV.setValue(typeInfo.getSQLCollation(), jdbcType, value, javaType, streamSetterArgs, cal, scale, con,
false);
}