Describe the bug
cursor.bulkcopy() does not behave consistently with a normal mssql_python.connect() session. The regular connection and a normal SELECT work, but bulkcopy() fails because it opens a separate internal connection and handles TLS differently.
What I observed:
mssql_python.connect(...) succeeded
-
SELECT @@SERVERNAME, DB_NAME(), SUSER_SNAME() on that same connection succeeded
-
cursor.bulkcopy(...) failed with: TLS handshake failed ... root certificate is not trusted
-
bulkcopy() only worked after forcing: Encrypt=yes;TrustServerCertificate=yes
Connection string used:
SERVER=<server>,1433;DATABASE=<database>;UID=...;PWD=...;Encrypt=no;TrustServerCertificate=no
Root cause (from inspecting the installed package):
In cursor.py, bulkcopy() reparses self.connection.connection_str and creates a fresh mssql_py_core.PyCoreConnection(...) for the bulk copy operation instead of reusing the already-open, working connection. Despite Encrypt=no being set in the connection string, the bulkcopy path still attempts a TLS handshake and fails certificate validation.
To reproduce
import mssql_python
conn = mssql_python.connect("SERVER=<server>,1433;DATABASE=<db>;UID=<user>;PWD=<pass>;Encrypt=no;TrustServerCertificate=no")
cursor = conn.cursor()
# This works fine
cursor.execute("SELECT @@SERVERNAME, DB_NAME(), SUSER_SNAME()")
print(cursor.fetchone())
# This fails with TLS handshake error
cursor.bulkcopy("INSERT BULK target_table ([col1] INT, [col2] NVARCHAR(100))", [{"col1": 1, "col2": "test"}])
Expected behavior
bulkcopy() should either:
- Reuse the existing working connection, or
-
- Honor the same connection-string encryption settings (
Encrypt=no) consistently when creating its internal connection
Further technical details
Python version: 3.12
SQL Server version: SQL Server 2019
Operating system: Windows
- mssql-python version: 1.4.0
-
- Driver: msodbcsql18.dll 18.05.0001
Additional context
Workaround: Setting Encrypt=yes;TrustServerCertificate=yes forces bulkcopy() to complete the TLS handshake without cert validation. This works but is not equivalent to Encrypt=no and shouldn't be necessary when the main connection path already works without encryption.
Describe the bug
cursor.bulkcopy()does not behave consistently with a normalmssql_python.connect()session. The regular connection and a normalSELECTwork, butbulkcopy()fails because it opens a separate internal connection and handles TLS differently.What I observed:
mssql_python.connect(...)succeededSELECT @@SERVERNAME, DB_NAME(), SUSER_SNAME()on that same connection succeededcursor.bulkcopy(...)failed with:TLS handshake failed ... root certificate is not trustedbulkcopy()only worked after forcing:Encrypt=yes;TrustServerCertificate=yesConnection string used:
Root cause (from inspecting the installed package):
In
cursor.py,bulkcopy()reparsesself.connection.connection_strand creates a freshmssql_py_core.PyCoreConnection(...)for the bulk copy operation instead of reusing the already-open, working connection. DespiteEncrypt=nobeing set in the connection string, thebulkcopypath still attempts a TLS handshake and fails certificate validation.To reproduce
Expected behavior
bulkcopy()should either:Encrypt=no) consistently when creating its internal connectionFurther technical details
Python version: 3.12
SQL Server version: SQL Server 2019
Operating system: Windows
Additional context
Workaround: Setting
Encrypt=yes;TrustServerCertificate=yesforcesbulkcopy()to complete the TLS handshake without cert validation. This works but is not equivalent toEncrypt=noand shouldn't be necessary when the main connection path already works without encryption.