From: Gord Thompson Date: Thu, 21 May 2020 22:20:48 +0000 (-0600) Subject: Stop converting mssql datetime.time parameters to datetime.datetime X-Git-Tag: rel_1_3_18~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4382299a49b988075a66d2d0da7cc58108f87831;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Stop converting mssql datetime.time parameters to datetime.datetime Fixes: #5339 Change-Id: Ida75422d8c3fdfc7adae68e547d88df49368a693 (cherry picked from commit 9a04c2f65754ac7bf93e0f58f68e59b41e43e67e) --- diff --git a/doc/build/changelog/unreleased_13/5339.rst b/doc/build/changelog/unreleased_13/5339.rst new file mode 100644 index 0000000000..efff6b2055 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5339.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: bug, mssql + :tickets: 5339 + + Fixed issue where ``datetime.time`` parameters were being converted to + ``datetime.datetime``, making them incompatible with comparisons like + ``>=`` against an actual :class:`_mssql.TIME` column. diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index 0a6e27a464..496df4dc27 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -967,7 +967,11 @@ class TIME(sqltypes.TIME): self.__zero_date, value.time() ) elif isinstance(value, datetime.time): - value = datetime.datetime.combine(self.__zero_date, value) + """ issue #5339 + per: https://github.com/mkleehammer/pyodbc/wiki/Tips-and-Tricks-by-Database-Platform#time-columns + pass TIME value as string + """ # noqa + value = str(value) return value return process diff --git a/test/dialect/mssql/test_types.py b/test/dialect/mssql/test_types.py index c95ac6e6d9..68b024f49d 100644 --- a/test/dialect/mssql/test_types.py +++ b/test/dialect/mssql/test_types.py @@ -56,6 +56,52 @@ from sqlalchemy.testing import pickleable from sqlalchemy.util import b +class TimeParameterTest(fixtures.TablesTest): + __only_on__ = "mssql" + __backend__ = True + + @classmethod + def define_tables(cls, metadata): + Table( + "time_t", + metadata, + Column("id", Integer, primary_key=True, autoincrement=False), + Column("time_col", Time), + ) + + @classmethod + def insert_data(cls, connection): + time_t = cls.tables.time_t + connection.execute( + time_t.insert(), + [ + {"id": 1, "time_col": datetime.time(1, 23, 45, 67)}, + {"id": 2, "time_col": datetime.time(12, 0, 0)}, + {"id": 3, "time_col": datetime.time(16, 19, 59, 999999)}, + {"id": 4, "time_col": None}, + ], + ) + + @testing.combinations( + ("not_null", datetime.time(1, 23, 45, 68), 2), + ("null", None, 1), + id_="iaa", + argnames="time_value, expected_row_count", + ) + def test_time_as_parameter_to_where( + self, time_value, expected_row_count, connection + ): + # issue #5339 + t = self.tables.time_t + + if time_value is None: + qry = t.select().where(t.c.time_col.is_(time_value)) + else: + qry = t.select().where(t.c.time_col >= time_value) + result = connection.execute(qry).fetchall() + eq_(len(result), expected_row_count) + + class TimeTypeTest(fixtures.TestBase): def test_result_processor_no_microseconds(self): expected = datetime.time(12, 34, 56)