summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-01-10 13:16:43 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2020-01-10 13:19:05 -0500
commit48b37a062a26a41bd5c9243d2365a6c06a77a347 (patch)
tree462255fb86475ee65690147063f52ce38963b47f
parent4b17d0306421cab9821125fb774d1ff89b36e77e (diff)
downloadsqlalchemy-48b37a062a26a41bd5c9243d2365a6c06a77a347.tar.gz
Integrate mapper-level version_id_col with versioned_history
as the versioned_history example supplies an integer version counter for the purposes of generating an audit trail, this counter is also suited to be used for optimistic concurrency detection using the version_id_col feature. Build upon the test that was first added in ac54ba0f2d8df5a76b6852841b6b3321c0e6c0e2 to provide a flag and some basic documentation. Fixes: #2861 Change-Id: I50236beae4c49b33ada8fdcc4c524273b4e21c75
-rw-r--r--examples/versioned_history/__init__.py20
-rw-r--r--examples/versioned_history/history_meta.py5
-rw-r--r--examples/versioned_history/test_versioning.py3
3 files changed, 26 insertions, 2 deletions
diff --git a/examples/versioned_history/__init__.py b/examples/versioned_history/__init__.py
index 1d271fb62..3deb7fcb2 100644
--- a/examples/versioned_history/__init__.py
+++ b/examples/versioned_history/__init__.py
@@ -61,6 +61,26 @@ can be applied::
SomeHistoryClass = SomeClass.__history_mapper__.class_
+The versioning example also integrates with the ORM optimistic concurrency
+feature documented at :ref:`mapper_version_counter`. To enable this feature,
+set the flag ``Versioned.use_mapper_versioning`` to True::
+
+ class SomeClass(Versioned, Base):
+ __tablename__ = 'sometable'
+
+ use_mapper_versioning = True
+
+ id = Column(Integer, primary_key=True)
+ name = Column(String(50))
+
+ def __eq__(self, other):
+ assert type(other) is SomeClass and other.id == self.id
+
+Above, if two instance of ``SomeClass`` with the same version identifier
+are updated and sent to the database for UPDATE concurrently, if the database
+isolation level allows the two UPDATE statements to proceed, one will fail
+because it no longer is against the last known version identifier.
+
.. autosource::
"""
diff --git a/examples/versioned_history/history_meta.py b/examples/versioned_history/history_meta.py
index 22b019bd7..eb824bd7b 100644
--- a/examples/versioned_history/history_meta.py
+++ b/examples/versioned_history/history_meta.py
@@ -168,9 +168,14 @@ def _history_mapper(local_mapper):
local_mapper.add_property(
"version", local_mapper.local_table.c.version
)
+ if cls.use_mapper_versioning:
+ local_mapper.version_id_col = local_mapper.local_table.c.version
class Versioned(object):
+ use_mapper_versioning = False
+ """if True, also assign the version column to be tracked by the mapper"""
+
@declared_attr
def __mapper_cls__(cls):
def map_(cls, *arg, **kw):
diff --git a/examples/versioned_history/test_versioning.py b/examples/versioned_history/test_versioning.py
index 44e545749..71a6b6ad2 100644
--- a/examples/versioned_history/test_versioning.py
+++ b/examples/versioned_history/test_versioning.py
@@ -128,12 +128,11 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
def test_w_mapper_versioning(self):
class SomeClass(Versioned, self.Base, ComparableEntity):
__tablename__ = "sometable"
+ use_mapper_versioning = True
id = Column(Integer, primary_key=True)
name = Column(String(50))
- SomeClass.__mapper__.version_id_col = SomeClass.__table__.c.version
-
self.create_tables()
sess = self.session
sc = SomeClass(name="sc1")