FIX: Removed aggressive datetime parsing by arvis108 · Pull Request #235 · microsoft/mssql-python
Work Item / Issue Reference
GitHub Issue: #234
Summary
Summary
This PR fixes a critical issue where string parameters were being automatically converted to datetime objects, causing failures in SQL queries that require string-to-string comparisons. The fix removes aggressive content-based datetime parsing from the _map_sql_type() method while preserving all existing functionality for actual datetime objects.
Problem
The mssql-python driver was failing on queries like:
cursor.execute("SELECT * FROM table WHERE RIGHT(column, 10) = ?", ('2025-08-12',))
This would throw datetime conversion errors because the driver was automatically trying to parse the string '2025-08-12' as a date object, even when it should remain a string for the RIGHT() function comparison.
Problematic Code (Before Fix):
if isinstance(param, str): # Attempt to parse as date, datetime, datetime2, timestamp, smalldatetime or time if self._parse_date(param): parameters_list[i] = self._parse_date(param) # MUTATION! return (SQL_DATE, SQL_C_TYPE_DATE, 10, 0, False) if self._parse_datetime(param): parameters_list[i] = self._parse_datetime(param) # MUTATION! return (SQL_TIMESTAMP, SQL_C_TYPE_TIMESTAMP, 26, 6, False) # ... more parsing attempts
Why This Was Wrong:
- Violated separation of concerns: Type mapping shouldn't do content parsing
- Unpredictable behavior: Same string could be treated differently in different contexts
- Data mutation: Modified user's parameter data without permission
- Against DB-API principles: Parameter binding should be based on Python type, not content
Solution
Approach: Follow PyMSSQL's proven type-based parameter mapping approach.
Key Changes:
- Removed automatic datetime parsing from
_map_sql_type()for string parameters - Strings now always map to VARCHAR/NVARCHAR based purely on Python type
Files Modified:
mssql_python/cursor.py: Simplified string parameter handling in_map_sql_type()tests/test_004_cursor.py: Added test for string parameter behavior
Before vs After
Before (Failed):
date_str = '2025-08-12' cursor.execute("SELECT * WHERE RIGHT(column, 10) = ?", (date_str,)) # DateTime conversion error
After (Works):
date_str = '2025-08-12' cursor.execute("SELECT * WHERE RIGHT(column, 10) = ?", (date_str,)) # Works correctly