]> 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 22:06:03 +0000 (17:06 -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
(cherry picked from commit 8607ae51fc5b74c181cdde6b89ade3ee30c12dad)

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 3a6f972e07428784d169ccac3bbc77f4d6c994fb..5da8a1ee1f74c36a7e1426839f112b94e4d582f7 100644 (file)
@@ -618,6 +618,7 @@ class ManyToOneDP(DependencyProcessor):
                 (before_delete, parent_pre_updates),
 
                 (parent_pre_updates, child_deletes),
+                (parent_pre_updates, parent_deletes),
             ])
         else:
             uow.dependencies.update([
index f3a7dd141c55b9894c04539002a2f90925546734..e2506cdac8948eb290279265334a40fffc7b5efd 100644 (file)
@@ -636,6 +636,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"""