private void writeSqlVariant()

in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java [2603:2835]


    private void writeSqlVariant(TDSWriter tdsWriter, Object colValue, ResultSet sourceResultSet, int srcColOrdinal,
            int destColOrdinal, int bulkJdbcType, int bulkScale, boolean isStreaming) throws SQLServerException {
        if (null == colValue) {
            writeNullToTdsWriter(tdsWriter, bulkJdbcType, isStreaming);
            return;
        }
        SqlVariant variantType = ((SQLServerResultSet) sourceResultSet).getVariantInternalType(srcColOrdinal);
        int baseType = variantType.getBaseType();
        byte[] srcBytes;
        // for sql variant we normally should return the colvalue for time as time string. but for
        // bulkcopy we need it to be timestamp. so we have to retrieve it again once we are in bulkcopy
        // and make sure that the base type is time.
        if (TDSType.TIMEN == TDSType.valueOf(baseType)) {
            variantType.setIsBaseTypeTimeValue(true);
            ((SQLServerResultSet) sourceResultSet).setInternalVariantType(srcColOrdinal, variantType);
            colValue = ((SQLServerResultSet) sourceResultSet).getObject(srcColOrdinal);
        }
        switch (TDSType.valueOf(baseType)) {
            case INT8:
                writeBulkCopySqlVariantHeader(10, TDSType.INT8.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeLong(Long.valueOf(colValue.toString()));
                break;

            case INT4:
                writeBulkCopySqlVariantHeader(6, TDSType.INT4.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeInt(Integer.valueOf(colValue.toString()));
                break;

            case INT2:
                writeBulkCopySqlVariantHeader(4, TDSType.INT2.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeShort(Short.valueOf(colValue.toString()));
                break;

            case INT1:
                writeBulkCopySqlVariantHeader(3, TDSType.INT1.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeByte(Byte.valueOf(colValue.toString()));
                break;

            case FLOAT8:
                writeBulkCopySqlVariantHeader(10, TDSType.FLOAT8.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeDouble(Double.valueOf(colValue.toString()));
                break;

            case FLOAT4:
                writeBulkCopySqlVariantHeader(6, TDSType.FLOAT4.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeReal(Float.valueOf(colValue.toString()));
                break;

            case MONEY8:
                // For decimalN we right TDSWriter.BIGDECIMAL_MAX_LENGTH as maximum length = 17
                // 17 + 2 for basetype and probBytes + 2 for precision and length = 21 the length of data in header
                writeBulkCopySqlVariantHeader(21, TDSType.DECIMALN.byteValue(), (byte) 2, tdsWriter);
                tdsWriter.writeByte((byte) 38);
                tdsWriter.writeByte((byte) 4);
                tdsWriter.writeSqlVariantInternalBigDecimal((BigDecimal) colValue, bulkJdbcType);
                break;

            case MONEY4:
                writeBulkCopySqlVariantHeader(21, TDSType.DECIMALN.byteValue(), (byte) 2, tdsWriter);
                tdsWriter.writeByte((byte) 38);
                tdsWriter.writeByte((byte) 4);
                tdsWriter.writeSqlVariantInternalBigDecimal((BigDecimal) colValue, bulkJdbcType);
                break;

            case BIT1:
                writeBulkCopySqlVariantHeader(3, TDSType.BIT1.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeByte((byte) (((Boolean) colValue).booleanValue() ? 1 : 0));
                break;

            case DATEN:
                writeBulkCopySqlVariantHeader(5, TDSType.DATEN.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeDate(colValue.toString());
                break;

            case TIMEN:
                int timeBulkScale = variantType.getScale();
                int timeHeaderLength = 0x08; // default
                if (2 >= timeBulkScale) {
                    timeHeaderLength = 0x06;
                } else if (4 >= timeBulkScale) {
                    timeHeaderLength = 0x07;
                } else {
                    timeHeaderLength = 0x08;
                }
                writeBulkCopySqlVariantHeader(timeHeaderLength, TDSType.TIMEN.byteValue(), (byte) 1, tdsWriter); // depending
                                                                                                                 // on
                                                                                                                 // scale,
                                                                                                                 // the
                                                                                                                 // header
                                                                                                                 // length
                // defers
                tdsWriter.writeByte((byte) timeBulkScale);
                tdsWriter.writeTime((java.sql.Timestamp) colValue, timeBulkScale);
                break;

            case DATETIME8:
                writeBulkCopySqlVariantHeader(10, TDSType.DATETIME8.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeDatetime(colValue.toString());
                break;

            case DATETIME4:
                // when the type is ambiguous, we write to bigger type
                writeBulkCopySqlVariantHeader(10, TDSType.DATETIME8.byteValue(), (byte) 0, tdsWriter);
                tdsWriter.writeDatetime(colValue.toString());
                break;

            case DATETIME2N:
                writeBulkCopySqlVariantHeader(10, TDSType.DATETIME2N.byteValue(), (byte) 1, tdsWriter); // 1 is
                                                                                                        // probbytes for
                                                                                                        // time
                tdsWriter.writeByte((byte) 0x03);
                String timeStampValue = colValue.toString();
                tdsWriter.writeTime(java.sql.Timestamp.valueOf(timeStampValue), 0x03); // datetime2 in sql_variant has
                                                                                       // up to scale 3 support
                // Send only the date part
                tdsWriter.writeDate(timeStampValue.substring(0, timeStampValue.lastIndexOf(' ')));
                break;

            case BIGCHAR:
                int length = colValue.toString().length();
                writeBulkCopySqlVariantHeader(9 + length, TDSType.BIGCHAR.byteValue(), (byte) 7, tdsWriter);
                tdsWriter.writeCollationForSqlVariant(variantType); // writes collation info and sortID
                tdsWriter.writeShort((short) (length));
                SQLCollation destCollation = destColumnMetadata.get(destColOrdinal).collation;
                if (null != destCollation) {
                    tdsWriter.writeBytes(colValue.toString()
                            .getBytes(destColumnMetadata.get(destColOrdinal).collation.getCharset()));
                } else {
                    tdsWriter.writeBytes(colValue.toString().getBytes());
                }
                break;

            case BIGVARCHAR:
                length = colValue.toString().length();
                writeBulkCopySqlVariantHeader(9 + length, TDSType.BIGVARCHAR.byteValue(), (byte) 7, tdsWriter);
                tdsWriter.writeCollationForSqlVariant(variantType); // writes collation info and sortID
                tdsWriter.writeShort((short) (length));

                destCollation = destColumnMetadata.get(destColOrdinal).collation;
                if (null != destCollation) {
                    tdsWriter.writeBytes(colValue.toString()
                            .getBytes(destColumnMetadata.get(destColOrdinal).collation.getCharset()));
                } else {
                    tdsWriter.writeBytes(colValue.toString().getBytes());
                }
                break;

            case NCHAR:
                length = colValue.toString().length() * 2;
                writeBulkCopySqlVariantHeader(9 + length, TDSType.NCHAR.byteValue(), (byte) 7, tdsWriter);
                tdsWriter.writeCollationForSqlVariant(variantType); // writes collation info and sortID
                int stringLength = colValue.toString().length();
                byte[] typevarlen = new byte[2];
                typevarlen[0] = (byte) (2 * stringLength & 0xFF);
                typevarlen[1] = (byte) ((2 * stringLength >> 8) & 0xFF);
                tdsWriter.writeBytes(typevarlen);
                tdsWriter.writeString(colValue.toString());
                break;

            case NVARCHAR:
                length = colValue.toString().length() * 2;
                writeBulkCopySqlVariantHeader(9 + length, TDSType.NVARCHAR.byteValue(), (byte) 7, tdsWriter);
                tdsWriter.writeCollationForSqlVariant(variantType); // writes collation info and sortID
                stringLength = colValue.toString().length();
                typevarlen = new byte[2];
                typevarlen[0] = (byte) (2 * stringLength & 0xFF);
                typevarlen[1] = (byte) ((2 * stringLength >> 8) & 0xFF);
                tdsWriter.writeBytes(typevarlen);
                tdsWriter.writeString(colValue.toString());
                break;

            case GUID:
                length = colValue.toString().length();
                writeBulkCopySqlVariantHeader(9 + length, TDSType.BIGCHAR.byteValue(), (byte) 7, tdsWriter);
                // since while reading collation from sourceMetaData in guid we don't read collation, cause we are
                // reading binary
                // but in writing it we are using char, we need to get the collation.
                SQLCollation collation = (null != destColumnMetadata.get(srcColOrdinal).collation) ? destColumnMetadata
                        .get(srcColOrdinal).collation : connection.getDatabaseCollation();
                variantType.setCollation(collation);
                tdsWriter.writeCollationForSqlVariant(variantType); // writes collation info and sortID
                tdsWriter.writeShort((short) (length));
                // converting string into destination collation using Charset
                destCollation = destColumnMetadata.get(destColOrdinal).collation;
                if (null != destCollation) {
                    tdsWriter.writeBytes(colValue.toString()
                            .getBytes(destColumnMetadata.get(destColOrdinal).collation.getCharset()));
                } else {
                    tdsWriter.writeBytes(colValue.toString().getBytes());
                }
                break;

            case BIGBINARY:
                byte[] b = (byte[]) colValue;
                length = b.length;
                writeBulkCopySqlVariantHeader(4 + length, TDSType.BIGVARBINARY.byteValue(), (byte) 2, tdsWriter);
                tdsWriter.writeShort((short) (variantType.getMaxLength())); // length
                if (colValue instanceof byte[]) {
                    srcBytes = (byte[]) colValue;
                } else {
                    try {
                        srcBytes = ParameterUtils.HexToBin(colValue.toString());
                    } catch (SQLServerException e) {
                        throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), e);
                    }
                }
                tdsWriter.writeBytes(srcBytes);
                break;

            case BIGVARBINARY:
                b = (byte[]) colValue;
                length = b.length;
                writeBulkCopySqlVariantHeader(4 + length, TDSType.BIGVARBINARY.byteValue(), (byte) 2, tdsWriter);
                tdsWriter.writeShort((short) (variantType.getMaxLength())); // length
                if (colValue instanceof byte[]) {
                    srcBytes = (byte[]) colValue;
                } else {
                    try {
                        srcBytes = ParameterUtils.HexToBin(colValue.toString());
                    } catch (SQLServerException e) {
                        throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), e);
                    }
                }
                tdsWriter.writeBytes(srcBytes);
                break;

            default:
                MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_BulkTypeNotSupported"));
                Object[] msgArgs = {JDBCType.of(bulkJdbcType).toString().toLowerCase(Locale.ENGLISH)};
                SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, true);
                break;
        }
    }