summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/testing
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2023-03-03 09:30:58 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2023-03-04 23:22:20 -0500
commitb38fb59fe484d6e4e5992c9b2dc9b9f7724f016a (patch)
tree21bac11da9981fe45b20bdb06240b37fb47b5800 /lib/sqlalchemy/testing
parent7099dd20e90307237240f30d5db0816a08356a5b (diff)
downloadsqlalchemy-b38fb59fe484d6e4e5992c9b2dc9b9f7724f016a.tar.gz
audition pymssql once more; retire sane_rowcount_returning
pymssql seems to be maintained again and seems to be working completely, so let's try re-enabling it. Fixed issue in the new :class:`.Uuid` datatype which prevented it from working with the pymssql driver. As pymssql seems to be maintained again, restored testing support for pymssql. Tweaked the pymssql dialect to take better advantage of RETURNING for INSERT statements in order to retrieve last inserted primary key values, in the same way as occurs for the mssql+pyodbc dialect right now. Identified that the ``sqlite`` and ``mssql+pyodbc`` dialects are now compatible with the SQLAlchemy ORM's "versioned rows" feature, since SQLAlchemy now computes rowcount for a RETURNING statement in this specific case by counting the rows returned, rather than relying upon ``cursor.rowcount``. In particular, the ORM versioned rows use case (documented at :ref:`mapper_version_counter`) should now be fully supported with the SQL Server pyodbc dialect. Change-Id: I38a0666587212327aecf8f98e86031ab25d1f14d References: #5321 Fixes: #9414
Diffstat (limited to 'lib/sqlalchemy/testing')
-rw-r--r--lib/sqlalchemy/testing/requirements.py25
-rw-r--r--lib/sqlalchemy/testing/suite/test_rowcount.py54
-rw-r--r--lib/sqlalchemy/testing/suite/test_types.py50
3 files changed, 115 insertions, 14 deletions
diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py
index 9bfc94e78..3332f7ce2 100644
--- a/lib/sqlalchemy/testing/requirements.py
+++ b/lib/sqlalchemy/testing/requirements.py
@@ -493,6 +493,13 @@ class SuiteRequirements(Requirements):
return exclusions.open()
@property
+ def arraysize(self):
+ """dialect includes the required pep-249 attribute
+ ``cursor.arraysize``"""
+
+ return exclusions.open()
+
+ @property
def emulated_lastrowid(self):
"""target dialect retrieves cursor.lastrowid, or fetches
from a database-side function after an insert() construct executes,
@@ -851,6 +858,24 @@ class SuiteRequirements(Requirements):
return exclusions.closed()
@property
+ def date_implicit_bound(self):
+ """target dialect when given a date object will bind it such
+ that the database server knows the object is a date, and not
+ a plain string.
+
+ """
+ return exclusions.open()
+
+ @property
+ def time_implicit_bound(self):
+ """target dialect when given a time object will bind it such
+ that the database server knows the object is a time, and not
+ a plain string.
+
+ """
+ return exclusions.open()
+
+ @property
def datetime_implicit_bound(self):
"""target dialect when given a datetime object will bind it such
that the database server knows the object is a datetime, and not
diff --git a/lib/sqlalchemy/testing/suite/test_rowcount.py b/lib/sqlalchemy/testing/suite/test_rowcount.py
index 8e19a24a8..ba8e10437 100644
--- a/lib/sqlalchemy/testing/suite/test_rowcount.py
+++ b/lib/sqlalchemy/testing/suite/test_rowcount.py
@@ -3,6 +3,7 @@
from sqlalchemy import bindparam
from sqlalchemy import Column
from sqlalchemy import Integer
+from sqlalchemy import MetaData
from sqlalchemy import select
from sqlalchemy import String
from sqlalchemy import Table
@@ -88,23 +89,58 @@ class RowCountTest(fixtures.TablesTest):
)
eq_(r.rowcount, 3)
- @testing.requires.update_returning
- def test_update_rowcount_return_defaults(self, connection):
+ @testing.variation("implicit_returning", [True, False])
+ @testing.variation(
+ "dml",
+ [
+ ("update", testing.requires.update_returning),
+ ("delete", testing.requires.delete_returning),
+ ],
+ )
+ def test_update_delete_rowcount_return_defaults(
+ self, connection, implicit_returning, dml
+ ):
"""note this test should succeed for all RETURNING backends
as of 2.0. In
Idf28379f8705e403a3c6a937f6a798a042ef2540 we changed rowcount to use
len(rows) when we have implicit returning
"""
- employees_table = self.tables.employees
+
+ if implicit_returning:
+ employees_table = self.tables.employees
+ else:
+ employees_table = Table(
+ "employees",
+ MetaData(),
+ Column(
+ "employee_id",
+ Integer,
+ autoincrement=False,
+ primary_key=True,
+ ),
+ Column("name", String(50)),
+ Column("department", String(1)),
+ implicit_returning=False,
+ )
department = employees_table.c.department
- stmt = (
- employees_table.update()
- .where(department == "C")
- .values(name=employees_table.c.department + "Z")
- .return_defaults()
- )
+
+ if dml.update:
+ stmt = (
+ employees_table.update()
+ .where(department == "C")
+ .values(name=employees_table.c.department + "Z")
+ .return_defaults()
+ )
+ elif dml.delete:
+ stmt = (
+ employees_table.delete()
+ .where(department == "C")
+ .return_defaults()
+ )
+ else:
+ dml.fail()
r = connection.execute(stmt)
eq_(r.rowcount, 3)
diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py
index d6a74b220..bc2885341 100644
--- a/lib/sqlalchemy/testing/suite/test_types.py
+++ b/lib/sqlalchemy/testing/suite/test_types.py
@@ -450,11 +450,6 @@ class _DateFixture(_LiteralRoundTripFixture, fixtures.TestBase):
Column("decorated_date_data", Decorated),
)
- @testing.requires.datetime_implicit_bound
- def test_select_direct(self, connection):
- result = connection.scalar(select(literal(self.data)))
- eq_(result, self.data)
-
def test_round_trip(self, connection):
date_table = self.tables.date_table
@@ -531,6 +526,11 @@ class DateTimeTest(_DateFixture, fixtures.TablesTest):
datatype = DateTime
data = datetime.datetime(2012, 10, 15, 12, 57, 18)
+ @testing.requires.datetime_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class DateTimeTZTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("datetime_timezone",)
@@ -540,6 +540,11 @@ class DateTimeTZTest(_DateFixture, fixtures.TablesTest):
2012, 10, 15, 12, 57, 18, tzinfo=datetime.timezone.utc
)
+ @testing.requires.datetime_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class DateTimeMicrosecondsTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("datetime_microseconds",)
@@ -566,6 +571,11 @@ class TimeTest(_DateFixture, fixtures.TablesTest):
datatype = Time
data = datetime.time(12, 57, 18)
+ @testing.requires.time_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class TimeTZTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("time_timezone",)
@@ -573,6 +583,11 @@ class TimeTZTest(_DateFixture, fixtures.TablesTest):
datatype = Time(timezone=True)
data = datetime.time(12, 57, 18, tzinfo=datetime.timezone.utc)
+ @testing.requires.time_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class TimeMicrosecondsTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("time_microseconds",)
@@ -580,6 +595,11 @@ class TimeMicrosecondsTest(_DateFixture, fixtures.TablesTest):
datatype = Time
data = datetime.time(12, 57, 18, 396)
+ @testing.requires.time_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class DateTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("date",)
@@ -587,6 +607,11 @@ class DateTest(_DateFixture, fixtures.TablesTest):
datatype = Date
data = datetime.date(2012, 10, 15)
+ @testing.requires.date_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class DateTimeCoercedToDateTimeTest(_DateFixture, fixtures.TablesTest):
"""this particular suite is testing that datetime parameters get
@@ -600,6 +625,11 @@ class DateTimeCoercedToDateTimeTest(_DateFixture, fixtures.TablesTest):
data = datetime.datetime(2012, 10, 15, 12, 57, 18)
compare = datetime.date(2012, 10, 15)
+ @testing.requires.datetime_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class DateTimeHistoricTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("datetime_historic",)
@@ -607,6 +637,11 @@ class DateTimeHistoricTest(_DateFixture, fixtures.TablesTest):
datatype = DateTime
data = datetime.datetime(1850, 11, 10, 11, 52, 35)
+ @testing.requires.date_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class DateHistoricTest(_DateFixture, fixtures.TablesTest):
__requires__ = ("date_historic",)
@@ -614,6 +649,11 @@ class DateHistoricTest(_DateFixture, fixtures.TablesTest):
datatype = Date
data = datetime.date(1727, 4, 1)
+ @testing.requires.date_implicit_bound
+ def test_select_direct(self, connection):
+ result = connection.scalar(select(literal(self.data)))
+ eq_(result, self.data)
+
class IntegerTest(_LiteralRoundTripFixture, fixtures.TestBase):
__backend__ = True