summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2023-03-05 20:29:27 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2023-03-05 20:29:27 +0000
commite3e99f7fe3339b26487a7e03c0d1acd9a83e2d70 (patch)
tree3b6780744aa754f85f38765485a624e385e77a67 /lib/sqlalchemy/dialects
parent94c8d4e2e3f31042fdc5dfd5f942494a3a81bdce (diff)
parentb38fb59fe484d6e4e5992c9b2dc9b9f7724f016a (diff)
downloadsqlalchemy-e3e99f7fe3339b26487a7e03c0d1acd9a83e2d70.tar.gz
Merge "audition pymssql once more; retire sane_rowcount_returning" into main
Diffstat (limited to 'lib/sqlalchemy/dialects')
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py38
-rw-r--r--lib/sqlalchemy/dialects/mssql/provision.py22
-rw-r--r--lib/sqlalchemy/dialects/mssql/pymssql.py6
-rw-r--r--lib/sqlalchemy/dialects/mssql/pyodbc.py11
-rw-r--r--lib/sqlalchemy/dialects/sqlite/base.py3
5 files changed, 48 insertions, 32 deletions
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index a30c57c7f..b970f6c0a 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -885,29 +885,20 @@ The SQL Server drivers may have limited ability to return the number
of rows updated from an UPDATE or DELETE statement.
As of this writing, the PyODBC driver is not able to return a rowcount when
-OUTPUT INSERTED is used. This impacts the SQLAlchemy ORM's versioning feature
-in many cases where server-side value generators are in use in that while the
-versioning operations can succeed, the ORM cannot always check that an UPDATE
-or DELETE statement matched the number of rows expected, which is how it
-verifies that the version identifier matched. When this condition occurs, a
-warning will be emitted but the operation will proceed.
-
-The use of OUTPUT INSERTED can be disabled by setting the
-:paramref:`_schema.Table.implicit_returning` flag to ``False`` on a particular
-:class:`_schema.Table`, which in declarative looks like::
-
- class MyTable(Base):
- __tablename__ = 'mytable'
- id = Column(Integer, primary_key=True)
- stuff = Column(String(10))
- timestamp = Column(TIMESTAMP(), default=text('DEFAULT'))
- __mapper_args__ = {
- 'version_id_col': timestamp,
- 'version_id_generator': False,
- }
- __table_args__ = {
- 'implicit_returning': False
- }
+OUTPUT INSERTED is used. Previous versions of SQLAlchemy therefore had
+limitations for features such as the "ORM Versioning" feature that relies upon
+accurate rowcounts in order to match version numbers with matched rows.
+
+SQLAlchemy 2.0 now retrieves the "rowcount" manually for these particular use
+cases based on counting the rows that arrived back within RETURNING; so while
+the driver still has this limitation, the ORM Versioning feature is no longer
+impacted by it. As of SQLAlchemy 2.0.5, ORM versioning has been fully
+re-enabled for the pyodbc driver.
+
+.. versionchanged:: 2.0.5 ORM versioning support is restored for the pyodbc
+ driver. Previously, a warning would be emitted during ORM flush that
+ versioning was not supported.
+
Enabling Snapshot Isolation
---------------------------
@@ -2965,6 +2956,7 @@ class MSDialect(default.DefaultDialect):
supports_statement_cache = True
supports_default_values = True
supports_empty_insert = False
+ favor_returning_over_lastrowid = True
supports_comments = True
supports_default_metavalue = False
diff --git a/lib/sqlalchemy/dialects/mssql/provision.py b/lib/sqlalchemy/dialects/mssql/provision.py
index a7ecf4aa3..336e10cd9 100644
--- a/lib/sqlalchemy/dialects/mssql/provision.py
+++ b/lib/sqlalchemy/dialects/mssql/provision.py
@@ -12,6 +12,7 @@ from ...schema import Table
from ...testing.provision import create_db
from ...testing.provision import drop_all_schema_objects_pre_tables
from ...testing.provision import drop_db
+from ...testing.provision import generate_driver_url
from ...testing.provision import get_temp_table_name
from ...testing.provision import log
from ...testing.provision import normalize_sequence
@@ -19,6 +20,27 @@ from ...testing.provision import run_reap_dbs
from ...testing.provision import temp_table_keyword_args
+@generate_driver_url.for_db("mssql")
+def generate_driver_url(url, driver, query_str):
+
+ backend = url.get_backend_name()
+
+ new_url = url.set(drivername="%s+%s" % (backend, driver))
+
+ if driver != "pyodbc":
+ new_url = new_url.set(query="")
+
+ if query_str:
+ new_url = new_url.update_query_string(query_str)
+
+ try:
+ new_url.get_dialect()
+ except exc.NoSuchModuleError:
+ return None
+ else:
+ return new_url
+
+
@create_db.for_db("mssql")
def _mssql_create_db(cfg, eng, ident):
with eng.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
diff --git a/lib/sqlalchemy/dialects/mssql/pymssql.py b/lib/sqlalchemy/dialects/mssql/pymssql.py
index 699f61714..3823db91b 100644
--- a/lib/sqlalchemy/dialects/mssql/pymssql.py
+++ b/lib/sqlalchemy/dialects/mssql/pymssql.py
@@ -16,10 +16,9 @@
pymssql is a Python module that provides a Python DBAPI interface around
`FreeTDS <https://www.freetds.org/>`_.
-.. note::
+.. versionchanged:: 2.0.5
- pymssql is currently not included in SQLAlchemy's continuous integration
- (CI) testing.
+ pymssql was restored to SQLAlchemy's continuous integration testing
""" # noqa
@@ -51,6 +50,7 @@ class MSIdentifierPreparer_pymssql(MSIdentifierPreparer):
class MSDialect_pymssql(MSDialect):
supports_statement_cache = True
supports_native_decimal = True
+ supports_native_uuid = True
driver = "pymssql"
preparer = MSIdentifierPreparer_pymssql
diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py
index 4546cabcd..3fa752565 100644
--- a/lib/sqlalchemy/dialects/mssql/pyodbc.py
+++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py
@@ -281,9 +281,9 @@ non-ODBC drivers such as pymssql where it works very well.
Rowcount Support
----------------
-Pyodbc only has partial support for rowcount. See the notes at
-:ref:`mssql_rowcount_versioning` for important notes when using ORM
-versioning.
+Previous limitations with the SQLAlchemy ORM's "versioned rows" feature with
+Pyodbc have been resolved as of SQLAlchemy 2.0.5. See the notes at
+:ref:`mssql_rowcount_versioning`.
.. _mssql_pyodbc_fastexecutemany:
@@ -607,11 +607,10 @@ class MSExecutionContext_pyodbc(MSExecutionContext):
class MSDialect_pyodbc(PyODBCConnector, MSDialect):
supports_statement_cache = True
- # mssql still has problems with this on Linux
+ # note this parameter is no longer used by the ORM or default dialect
+ # see #9414
supports_sane_rowcount_returning = False
- favor_returning_over_lastrowid = True
-
execution_ctx_cls = MSExecutionContext_pyodbc
colspecs = util.update_copy(
diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py
index fcabf5bb8..20065d88e 100644
--- a/lib/sqlalchemy/dialects/sqlite/base.py
+++ b/lib/sqlalchemy/dialects/sqlite/base.py
@@ -1910,7 +1910,10 @@ class SQLiteDialect(default.DefaultDialect):
supports_default_values = True
supports_default_metavalue = False
+ # sqlite issue:
# https://github.com/python/cpython/issues/93421
+ # note this parameter is no longer used by the ORM or default dialect
+ # see #9414
supports_sane_rowcount_returning = False
supports_empty_insert = False