private String getDestTypeFromSrcType()

in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java [1210:1461]


    private String getDestTypeFromSrcType(int srcColIndx, int destColIndx,
            TDSWriter tdsWriter) throws SQLServerException {
        boolean isStreaming;

        SSType destSSType = (null != destColumnMetadata.get(destColIndx).cryptoMeta) ? destColumnMetadata
                .get(destColIndx).cryptoMeta.baseTypeInfo.getSSType() : destColumnMetadata.get(destColIndx).ssType;

        int bulkJdbcType, bulkPrecision, bulkScale;
        int srcPrecision;

        bulkJdbcType = srcColumnMetadata.get(srcColIndx).jdbcType;

        // For char/varchar precision is the size.
        bulkPrecision = srcPrecision = srcColumnMetadata.get(srcColIndx).precision;
        int destPrecision = destColumnMetadata.get(destColIndx).precision;
        bulkScale = srcColumnMetadata.get(srcColIndx).scale;

        CryptoMetadata destCryptoMeta = destColumnMetadata.get(destColIndx).cryptoMeta;
        if (null != destCryptoMeta || (null == destCryptoMeta && copyOptions.isAllowEncryptedValueModifications())) {
            // Encrypted columns are sent as binary data.
            tdsWriter.setCryptoMetaData(destColumnMetadata.get(destColIndx).cryptoMeta);

            /*
             * if source is encrypted and destination is unencrypted, use destination's sql type to send since there is
             * no way of finding if source is encrypted without accessing the resultset. Send destination type if source
             * resultset set is of type SQLServer, encryption is enabled and destination column is not encrypted
             */
            if ((sourceResultSet instanceof SQLServerResultSet) && (connection.isColumnEncryptionSettingEnabled())
                    && (null != destCryptoMeta)) {
                bulkJdbcType = destColumnMetadata.get(destColIndx).jdbcType;
                bulkPrecision = destPrecision;
                bulkScale = destColumnMetadata.get(destColIndx).scale;
            }

            // if destination is encrypted send metadata from destination and not from source
            if (DataTypes.SHORT_VARTYPE_MAX_BYTES < destPrecision) {
                return "varbinary(max)";
            } else {
                return "varbinary(" + destColumnMetadata.get(destColIndx).precision + ")";
            }
        }

        // isAllowEncryptedValueModifications is used only with source result set.
        if ((null != sourceResultSet) && (null != destColumnMetadata.get(destColIndx).encryptionType)
                && copyOptions.isAllowEncryptedValueModifications()) {
            return "varbinary(" + bulkPrecision + ")";
        }
        bulkPrecision = validateSourcePrecision(srcPrecision, bulkJdbcType, destPrecision);

        if ((java.sql.Types.NCHAR == bulkJdbcType) || (java.sql.Types.NVARCHAR == bulkJdbcType)
                || (java.sql.Types.LONGNVARCHAR == bulkJdbcType)) {
            isStreaming = (DataTypes.SHORT_VARTYPE_MAX_CHARS < srcPrecision)
                    || (DataTypes.SHORT_VARTYPE_MAX_CHARS < destPrecision);
        } else {
            isStreaming = (DataTypes.SHORT_VARTYPE_MAX_BYTES < srcPrecision)
                    || (DataTypes.SHORT_VARTYPE_MAX_BYTES < destPrecision);
        }

        // SQL Server does not convert string to binary, we will have to explicitly convert before sending.
        if (Util.isCharType(bulkJdbcType) && Util.isBinaryType(destSSType)) {
            if (isStreaming)
                return "varbinary(max)";
            else
                // Return binary(n) or varbinary(n) or varbinary(max) depending on destination type/precision.
                return destSSType.toString() + "("
                        + ((DataTypes.SHORT_VARTYPE_MAX_BYTES < destPrecision) ? "max" : destPrecision) + ")";
        }

        switch (bulkJdbcType) {
            case java.sql.Types.INTEGER:
                return "int";

            case java.sql.Types.SMALLINT:
                return "smallint";

            case java.sql.Types.BIGINT:
                return "bigint";

            case java.sql.Types.BIT:
                return "bit";

            case java.sql.Types.TINYINT:
                return "tinyint";

            case java.sql.Types.FLOAT:
            case java.sql.Types.DOUBLE:
                return "float";

            case java.sql.Types.REAL:
                return "real";

            case microsoft.sql.Types.MONEY:
                return "money";
            case microsoft.sql.Types.SMALLMONEY:
                return "smallmoney";
            case java.sql.Types.DECIMAL:
                /*
                 * SQL Server allows the insertion of decimal and numeric into a money (and smallmoney) column, but
                 * Azure DW only accepts money types for money column. To make the code compatible against both SQL
                 * Server and Azure DW, always send decimal and numeric as money/smallmoney if the destination column is
                 * money/smallmoney and the source is decimal/numeric.
                 */
                if (destSSType == SSType.MONEY) {
                    return "money";
                } else if (destSSType == SSType.SMALLMONEY) {
                    return "smallmoney";
                }
                return "decimal(" + bulkPrecision + ", " + bulkScale + ")";

            case java.sql.Types.NUMERIC:
                if (destSSType == SSType.MONEY) {
                    return "money";
                } else if (destSSType == SSType.SMALLMONEY) {
                    return "smallmoney";
                }
                return "numeric(" + bulkPrecision + ", " + bulkScale + ")";

            case microsoft.sql.Types.GUID:
                // For char the value has to be between 0 to 8000.
                return "char(" + bulkPrecision + ")";
            case java.sql.Types.CHAR:
                if (unicodeConversionRequired(bulkJdbcType, destSSType)) {
                    return "nchar(" + bulkPrecision + ")";
                } else {
                    return "char(" + bulkPrecision + ")";
                }
            case java.sql.Types.NCHAR:
                return "NCHAR(" + bulkPrecision + ")";

            case java.sql.Types.LONGVARCHAR:
            case java.sql.Types.VARCHAR:
                // Here the actual size of the varchar is used from the source table.
                // Doesn't need to match with the exact size of data or with the destination column size.
                if (unicodeConversionRequired(bulkJdbcType, destSSType)) {
                    if (isStreaming) {
                        return "nvarchar(max)";
                    } else {
                        return "nvarchar(" + bulkPrecision + ")";
                    }
                } else {
                    if (isStreaming) {
                        return "varchar(max)";
                    } else {
                        return "varchar(" + bulkPrecision + ")";
                    }
                }
                // For INSERT BULK operations, XMLTYPE is to be sent as NVARCHAR(N) or NVARCHAR(MAX) data type.
                // An error is produced if XMLTYPE is specified.
            case java.sql.Types.LONGNVARCHAR:
            case java.sql.Types.NVARCHAR:
                if (isStreaming) {
                    return "NVARCHAR(MAX)";
                } else {
                    return "NVARCHAR(" + bulkPrecision + ")";
                }

            case java.sql.Types.BINARY:
                // For binary the value has to be between 0 to 8000.
                return "binary(" + bulkPrecision + ")";

            case java.sql.Types.LONGVARBINARY:
            case java.sql.Types.VARBINARY:
                if (isStreaming)
                    return "varbinary(max)";
                else
                    return "varbinary(" + bulkPrecision + ")";

            case microsoft.sql.Types.DATETIME:
            case microsoft.sql.Types.SMALLDATETIME:
            case java.sql.Types.TIMESTAMP:
                switch (destSSType) {
                    case SMALLDATETIME:
                        if (null != serverBulkData && connection.getSendTemporalDataTypesAsStringForBulkCopy()) {
                            return "varchar("
                                    + ((0 == bulkPrecision) ? sourceBulkRecordTemporalMaxPrecision : bulkPrecision)
                                    + ")";
                        } else {
                            return "smalldatetime";
                        }
                    case DATETIME:
                        if (null != serverBulkData && connection.getSendTemporalDataTypesAsStringForBulkCopy()) {
                            return "varchar("
                                    + ((0 == bulkPrecision) ? sourceBulkRecordTemporalMaxPrecision : bulkPrecision)
                                    + ")";
                        } else {
                            return "datetime";
                        }
                    default:
                        // datetime2
                        /*
                         * If encrypted, varbinary will be returned before. The code will come here only if unencrypted.
                         * For unencrypted bulk copy if the source is CSV, we send the data as varchar and SQL Server
                         * will do the conversion. if the source is ResultSet, we send the data as the corresponding
                         * temporal type.
                         */
                        if (null != serverBulkData && connection.getSendTemporalDataTypesAsStringForBulkCopy()) {
                            return "varchar(" + ((0 == bulkPrecision) ? destPrecision : bulkPrecision) + ")";
                        } else {
                            return "datetime2(" + bulkScale + ")";
                        }
                }

            case java.sql.Types.DATE:
                /*
                 * If encrypted, varbinary will be returned before. The code will come here only if unencrypted. For
                 * unencrypted bulk copy if the source is CSV, we send the data as varchar and SQL Server will do the
                 * conversion. if the source is ResultSet, we send the data as the corresponding temporal type.
                 */
                if (null != serverBulkData && connection.getSendTemporalDataTypesAsStringForBulkCopy()) {
                    return "varchar(" + ((0 == bulkPrecision) ? destPrecision : bulkPrecision) + ")";
                } else {
                    return "date";
                }

            case java.sql.Types.TIME:
                /*
                 * If encrypted, varbinary will be returned before. The code will come here only if unencrypted. For
                 * unencrypted bulk copy if the source is CSV, we send the data as varchar and SQL Server will do the
                 * conversion. if the source is ResultSet, we send the data as the corresponding temporal type.
                 */
                if (null != serverBulkData && connection.getSendTemporalDataTypesAsStringForBulkCopy()) {
                    return "varchar(" + ((0 == bulkPrecision) ? destPrecision : bulkPrecision) + ")";
                } else {
                    return "time(" + bulkScale + ")";
                }

                // Return DATETIMEOFFSET for TIME_WITH_TIMEZONE and TIMESTAMP_WITH_TIMEZONE
            case 2013: // java.sql.Types.TIME_WITH_TIMEZONE
            case 2014: // java.sql.Types.TIMESTAMP_WITH_TIMEZONE
                return "datetimeoffset(" + bulkScale + ")";

            case microsoft.sql.Types.DATETIMEOFFSET:
                /*
                 * If encrypted, varbinary will be returned before. The code will come here only if unencrypted. For
                 * unencrypted bulk copy if the source is CSV, we send the data as varchar and SQL Server will do the
                 * conversion. if the source is ResultSet, we send the data as the corresponding temporal type.
                 */
                if (null != serverBulkData && connection.getSendTemporalDataTypesAsStringForBulkCopy()) {
                    return "varchar(" + ((0 == bulkPrecision) ? destPrecision : bulkPrecision) + ")";
                } else {
                    return "datetimeoffset(" + bulkScale + ")";
                }
            case microsoft.sql.Types.SQL_VARIANT:
                return "sql_variant";
            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);
            }
        }
        return null;
    }