]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add dependency for parent_pre post updates to parent deletes
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 12 Feb 2018 21:45:39 +0000 (16:45 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 12 Feb 2018 21:45:39 +0000 (16:45 -0500)
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
doc/build/changelog/unreleased_11/4187.rst [new file with mode: 0644]
lib/sqlalchemy/orm/dependency.py
test/orm/test_cycles.py

diff --git a/doc/build/changelog/unreleased_11/4187.rst b/doc/build/changelog/unreleased_11/4187.rst
new file mode 100644 (file)
index 0000000..4be100e
--- /dev/null
@@ -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.
index f05096a57b472f0a07ef0c308fdea563ca595340..799e633b3fad07e63445f8c558a519f1572b3d7f 100644 (file)
@@ -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([
index abd05067aa868e1ccc6e34555cdae191a66d76ad..7528d9696f18ecd4c8e2bd8066c37ba500021b0a 100644 (file)
@@ -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"""