Skip to content

Conversation

@muskan124947
Copy link
Contributor

@muskan124947 muskan124947 commented Oct 30, 2025

Description

GitHub issue : setBinaryStream() fails with Bulk Copy for Batch Insert in JDBC Driver 13.2.0
When using Bulk Copy for Batch Insert with setUseBulkCopyForBatchInsert(true) and inserting data into a [VARBINARY(MAX) column using PreparedStatement.setBinaryStream(), the insert operation fails with the following error:

com.microsoft.sqlserver.jdbc.SQLServerException: The string is not in a valid hex format.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:250)
    at com.microsoft.sqlserver.jdbc.ParameterUtils.hexToBin(ParameterUtils.java:21)
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.writeColumnToTdsWriter(SQLServerBulkCopy.java:2619)
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.writeColumn(SQLServerBulkCopy.java:3307)
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.writeBatchData(SQLServerBulkCopy.java:3886)
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.doInsertBulk(SQLServerBulkCopy.java:1703)

Root cause

The issue lies in the convertValue method within SQLServerBulkBatchInsertRecord. The method correctly handles byte[] arrays for binary data types but does not handle InputStream objects.

case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
case Types.BLOB: {
    if (data instanceof byte[]) {
        /*
         * if the binary data comes in as a byte array through setBytes through Bulk Copy for Batch Insert
         * API, don't turn the binary array into a string.
         */
        return data;
    } else {
        // Strip off 0x if present.
        String binData = data.toString().trim();
        if (binData.startsWith("0x") || binData.startsWith("0X")) {
            return binData.substring(2);
        } else {
            return binData;
        }
    }
}

When setBinaryStream() is used, the InputStream object falls into the else clause, causing data.toString() to return the Java object string representation (e.g., [java.io.ByteArrayInputStream@4e25154f]), which the driver later tries to interpret as hex data, resulting in the "invalid hex format" exception.

Fix

Modified the condition in the convertValue method to handle both byte[] and InputStream objects as binary data

if (data instanceof byte[] || data instanceof InputStream) {
        /*
         * if the binary data comes in as a byte array or Input Stream through setBytes/setBinaryStream 
         * through Bulk Copy for Batch Insert API, don't turn the binary array into a string.
         */
        return data;
    }

Testing

Added comprehensive test case testBulkCopyBatchInsertForInputStreamData in BatchExecutionWithBulkCopyTest that:

  • Creates a table with [VARBINARY(MAX) column
  • Uses [PreparedStatement.setBinaryStream() with [ByteArrayInputStream]
  • Executes batch insert with bulk copy enabled
  • Validates that the binary data is correctly inserted and retrieved

@codecov
Copy link

codecov bot commented Oct 30, 2025

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 52.30%. Comparing base (02e077c) to head (cc9a65b).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #2826      +/-   ##
============================================
+ Coverage     52.26%   52.30%   +0.04%     
- Complexity     4152     4160       +8     
============================================
  Files           149      149              
  Lines         34378    34378              
  Branches       5734     5734              
============================================
+ Hits          17966    17980      +14     
+ Misses        13918    13905      -13     
+ Partials       2494     2493       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Ananya2
Copy link
Contributor

Ananya2 commented Oct 30, 2025

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@Ananya2
Copy link
Contributor

Ananya2 commented Oct 30, 2025

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@Ananya2
Copy link
Contributor

Ananya2 commented Oct 30, 2025

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@muskan124947
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@muskan124947 muskan124947 added the Under Review Used for pull requests under review label Oct 31, 2025
@muskan124947 muskan124947 added this to the 13.3.0 milestone Oct 31, 2025
@muskan124947 muskan124947 merged commit 08ba857 into main Nov 4, 2025
18 of 19 checks passed
@divang divang removed the Under Review Used for pull requests under review label Nov 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

setBinaryStream() fails with Bulk Copy for Batch Insert in JDBC Driver 13.2.0

5 participants