void updateValue()

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);
    }