From: Mike Bayer Date: Mon, 12 Feb 2018 21:45:39 +0000 (-0500) Subject: Add dependency for parent_pre post updates to parent deletes X-Git-Tag: rel_1_2_3~10^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8607ae51fc5b74c181cdde6b89ade3ee30c12dad;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add dependency for parent_pre post updates to parent deletes Fixed issue in post_update feature where an UPDATE is emitted when the parent object has been deleted but the dependent object is not. This issue has existed for a long time however since 1.2 now asserts rows matched for post_update, this was raising an error. Change-Id: I31b1d22408e358962577435f0c4cb9a456ba0872 Fixes: #4187 --- diff --git a/doc/build/changelog/unreleased_11/4187.rst b/doc/build/changelog/unreleased_11/4187.rst new file mode 100644 index 0000000000..4be100e092 --- /dev/null +++ b/doc/build/changelog/unreleased_11/4187.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, orm + :tickets: 4187 + :versions: 1.2.3 + + Fixed issue in post_update feature where an UPDATE is emitted + when the parent object has been deleted but the dependent object + is not. This issue has existed for a long time however + since 1.2 now asserts rows matched for post_update, this + was raising an error. diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index f05096a57b..799e633b3f 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -607,6 +607,7 @@ class ManyToOneDP(DependencyProcessor): (before_delete, parent_pre_updates), (parent_pre_updates, child_deletes), + (parent_pre_updates, parent_deletes), ]) else: uow.dependencies.update([ diff --git a/test/orm/test_cycles.py b/test/orm/test_cycles.py index abd05067aa..7528d9696f 100644 --- a/test/orm/test_cycles.py +++ b/test/orm/test_cycles.py @@ -639,6 +639,40 @@ class OneToManyManyToOneTest(fixtures.MappedTest): sess.add(p) sess.flush() + def test_post_update_m2o_no_cascade(self): + person, ball, Ball, Person = (self.tables.person, + self.tables.ball, + self.classes.Ball, + self.classes.Person) + + mapper(Ball, ball) + mapper(Person, person, properties=dict( + favorite=relationship( + Ball, primaryjoin=person.c.favorite_ball_id == ball.c.id, + post_update=True))) + b = Ball(data='some data') + p = Person(data='some data') + p.favorite = b + sess = create_session() + sess.add(b) + sess.add(p) + sess.flush() + + sess.delete(p) + self.assert_sql_execution( + testing.db, + sess.flush, + CompiledSQL("UPDATE person SET favorite_ball_id=:favorite_ball_id " + "WHERE person.id = :person_id", + lambda ctx: { + 'favorite_ball_id': None, + 'person_id': p.id} + ), + CompiledSQL("DELETE FROM person WHERE person.id = :id", + lambda ctx: {'id': p.id} + ), + ) + def test_post_update_m2o(self): """A cycle between two rows, with a post_update on the many-to-one"""