add_output_converter documents/accepts an integer SQL type, but dispatch keys on the Python type (integer keys silently never fire) · Issue #684 · microsoft/mssql-python · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
add_output_converter documents/accepts an integer SQL type, but dispatch keys on the Python type (integer keys silently never fire) #684
Connection.add_output_converter(sqltype, func) is documented to take an integer ODBC SQL type code (pyodbc-compatible signature), but at fetch time the converter is looked up by the Python type stored in cursor.description[i][1]. As a result, registering a converter with an integer SQL type constant (for example SQL_DECIMAL) silently no-ops, and the value comes back unconverted. Only registering the Python type (for example decimal.Decimal) works.
Verified against mssql-python 1.11.0.
Repro
importmssql_pythonimportdecimalconn=mssql_python.connect(connection_string)
# Documented style: register by integer SQL type constant -> silently ignoredconn.add_output_converter(mssql_python.SQL_DECIMAL, lambdav: NoneifvisNoneelsefloat(v))
cur=conn.cursor()
cur.execute("SELECT TOP 1 ListPrice FROM Production.Product WHERE ListPrice > 0")
print(type(cur.fetchone()[0])) # <class 'decimal.Decimal'> (converter never ran)# Works only when keyed by the Python typeconn.add_output_converter(decimal.Decimal, lambdav: NoneifvisNoneelsefloat(v))
cur.execute("SELECT TOP 1 ListPrice FROM Production.Product WHERE ListPrice > 0")
print(type(cur.fetchone()[0])) # <class 'float'> (fires for money and decimal columns)
Expected
Either:
the integer SQL type key documented in the API works, or
the docstring reflects that the key is a Python type.
Ideally the method accepts both an integer SQL type code and a Python type (see suggested fix).
Actual
Registering an integer SQL type constant is stored but never matched, so no conversion occurs.
Registering the Python type works, and (because many SQL types collapse to one Python type) a single decimal.Decimal converter fires for decimal, numeric, money, and smallmoney columns alike.
Root cause
The description type code is a Python type, not the ODBC integer code. Cursor._map_data_type maps the ODBC SQL type code to a Python type for cursor.description[i][1]:
Cursor._build_converter_map then looks up the converter using that Python type:
# cursor.py, _build_converter_mapsql_type=desc[1] # this is a Python type, e.g. decimal.Decimalconverter=self.connection.get_output_converter(sql_type)
But add_output_converter documents and stores an integer key:
# connection.pydefadd_output_converter(self, sqltype: int, func):
""" Args: sqltype (int): The integer SQL type value to convert ... (e.g. SQL_VARCHAR) ... """self._output_converters[sqltype] =func
So the stored integer key can never match the Python-type lookup key. Note the sibling methods already hint at the intended design: get_output_converter and remove_output_converter are typed sqltype: Union[int, type].
A secondary docstring inaccuracy: add_output_converter says the value passed to the converter "will be a bytes object", but in practice the converter receives the already-decoded Python object (for example a decimal.Decimal), not raw bytes.
Suggested fix — support both int and Python types
Could add_output_converter accept both an integer SQL type code and a Python type? A minimal approach: when an integer SQL type code is registered, also index it under the corresponding Python type using the same SQL type code -> Python type mapping that _map_data_type uses (or have _build_converter_map fall back to the integer code for the column). That would make the documented pyodbc-style integer keys work while keeping the current Python-type keys, and it would preserve pyodbc source compatibility.
If integer keys are intentionally unsupported, then the add_output_converter docstring and signature should be updated to document the Python-type key (Union[int, type], matching the getters) and to correct the "bytes object" wording.
Activity
github-actions commentedon Jul 16, 2026
Hi David Levy (@dlevy-msft-sql), thank you for opening this issue!
Our team will review it shortly. We aim to triage all new issues within 24-48 hours and get back to you.
If you have additional information to share, please feel free to update the issue.
Thank you for your patience!
FIX: update output-converter exception test for GH #684 integer-key d…
FIX: make GH #684 metadata converter test black-box
TEST: cover execute() describe-failure reset of _column_sql_types (GH #…
FIX: document output-converter no-op keys and add comprehensive tests…
FIX: dispatch output converters on integer ODBC SQL type codes (#684) (…
jahnvi480 commentedon Aug 3, 2026
Code has been merged and will be fixed in our next release
RELEASE:1.13.0 (#707)