Skip to content

Commit c4b594e

Browse files
authored
FIX: Removed aggressive datetime parsing (#235)
1 parent 25131df commit c4b594e

File tree

2 files changed

+84
-33
lines changed

2 files changed

+84
-33
lines changed

mssql_python/cursor.py

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def _map_sql_type(self, param, parameters_list, i, min_val=None, max_val=None):
362362
0,
363363
False,
364364
)
365-
365+
366366
try:
367367
val = uuid.UUID(param)
368368
parameters_list[i] = val.bytes_le
@@ -376,38 +376,6 @@ def _map_sql_type(self, param, parameters_list, i, min_val=None, max_val=None):
376376
except ValueError:
377377
pass
378378

379-
380-
# Attempt to parse as date, datetime, datetime2, timestamp, smalldatetime or time
381-
if self._parse_date(param):
382-
parameters_list[i] = self._parse_date(
383-
param
384-
) # Replace the parameter with the date object
385-
return (
386-
ddbc_sql_const.SQL_DATE.value,
387-
ddbc_sql_const.SQL_C_TYPE_DATE.value,
388-
10,
389-
0,
390-
False,
391-
)
392-
if self._parse_datetime(param):
393-
parameters_list[i] = self._parse_datetime(param)
394-
return (
395-
ddbc_sql_const.SQL_TIMESTAMP.value,
396-
ddbc_sql_const.SQL_C_TYPE_TIMESTAMP.value,
397-
26,
398-
6,
399-
False,
400-
)
401-
if self._parse_time(param):
402-
parameters_list[i] = self._parse_time(param)
403-
return (
404-
ddbc_sql_const.SQL_TIME.value,
405-
ddbc_sql_const.SQL_C_TYPE_TIME.value,
406-
8,
407-
0,
408-
False,
409-
)
410-
411379
# String mapping logic here
412380
is_unicode = self._is_unicode_string(param)
413381

tests/test_004_cursor.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10661,6 +10661,89 @@ def test_decimal_separator_calculations(cursor, db_connection):
1066110661
# Cleanup
1066210662
cursor.execute("DROP TABLE IF EXISTS #pytest_decimal_calc_test")
1066310663

10664+
def test_date_string_parameter_binding(cursor, db_connection):
10665+
"""Verify that date-like strings are treated as strings in parameter binding"""
10666+
table_name = "#pytest_date_string"
10667+
try:
10668+
drop_table_if_exists(cursor, table_name)
10669+
cursor.execute(f"""
10670+
CREATE TABLE {table_name} (
10671+
a_column VARCHAR(20)
10672+
)
10673+
""")
10674+
cursor.execute(f"INSERT INTO {table_name} (a_column) VALUES ('string1'), ('string2')")
10675+
db_connection.commit()
10676+
10677+
date_str = "2025-08-12"
10678+
10679+
# Should fail to match anything, since binding may treat it as DATE not VARCHAR
10680+
cursor.execute(f"SELECT a_column FROM {table_name} WHERE RIGHT(a_column, 10) = ?", (date_str,))
10681+
rows = cursor.fetchall()
10682+
10683+
assert rows == [], f"Expected no match for date-like string, got {rows}"
10684+
10685+
except Exception as e:
10686+
pytest.fail(f"Date string parameter binding test failed: {e}")
10687+
finally:
10688+
drop_table_if_exists(cursor, table_name)
10689+
db_connection.commit()
10690+
10691+
def test_time_string_parameter_binding(cursor, db_connection):
10692+
"""Verify that time-like strings are treated as strings in parameter binding"""
10693+
table_name = "#pytest_time_string"
10694+
try:
10695+
drop_table_if_exists(cursor, table_name)
10696+
cursor.execute(f"""
10697+
CREATE TABLE {table_name} (
10698+
time_col VARCHAR(22)
10699+
)
10700+
""")
10701+
cursor.execute(f"INSERT INTO {table_name} (time_col) VALUES ('prefix_14:30:45_suffix')")
10702+
db_connection.commit()
10703+
10704+
time_str = "14:30:45"
10705+
10706+
# This should fail because '14:30:45' gets converted to TIME type
10707+
# and SQL Server can't compare TIME against VARCHAR with prefix/suffix
10708+
cursor.execute(f"SELECT time_col FROM {table_name} WHERE time_col = ?", (time_str,))
10709+
rows = cursor.fetchall()
10710+
10711+
assert rows == [], f"Expected no match for time-like string, got {rows}"
10712+
10713+
except Exception as e:
10714+
pytest.fail(f"Time string parameter binding test failed: {e}")
10715+
finally:
10716+
drop_table_if_exists(cursor, table_name)
10717+
db_connection.commit()
10718+
10719+
def test_datetime_string_parameter_binding(cursor, db_connection):
10720+
"""Verify that datetime-like strings are treated as strings in parameter binding"""
10721+
table_name = "#pytest_datetime_string"
10722+
try:
10723+
drop_table_if_exists(cursor, table_name)
10724+
cursor.execute(f"""
10725+
CREATE TABLE {table_name} (
10726+
datetime_col VARCHAR(33)
10727+
)
10728+
""")
10729+
cursor.execute(f"INSERT INTO {table_name} (datetime_col) VALUES ('prefix_2025-08-12T14:30:45_suffix')")
10730+
db_connection.commit()
10731+
10732+
datetime_str = "2025-08-12T14:30:45"
10733+
10734+
# This should fail because '2025-08-12T14:30:45' gets converted to TIMESTAMP type
10735+
# and SQL Server can't compare TIMESTAMP against VARCHAR with prefix/suffix
10736+
cursor.execute(f"SELECT datetime_col FROM {table_name} WHERE datetime_col = ?", (datetime_str,))
10737+
rows = cursor.fetchall()
10738+
10739+
assert rows == [], f"Expected no match for datetime-like string, got {rows}"
10740+
10741+
except Exception as e:
10742+
pytest.fail(f"Datetime string parameter binding test failed: {e}")
10743+
finally:
10744+
drop_table_if_exists(cursor, table_name)
10745+
db_connection.commit()
10746+
1066410747
def test_close(db_connection):
1066510748
"""Test closing the cursor"""
1066610749
try:

0 commit comments

Comments
 (0)