From: Mike Bayer Date: Fri, 10 Jan 2020 18:16:43 +0000 (-0500) Subject: Integrate mapper-level version_id_col with versioned_history X-Git-Tag: rel_1_3_13~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e48bcb599b107ce674d503df728e1f6f7b3603dc;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git 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 (cherry picked from commit 48b37a062a26a41bd5c9243d2365a6c06a77a347) --- diff --git a/examples/versioned_history/__init__.py b/examples/versioned_history/__init__.py index 1d271fb626..3deb7fcb2f 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 22b019bd70..eb824bd7b6 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 44e5457494..71a6b6ad2c 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")