#28099: Global use of UpdateQuery breaks complex delete updates
-------------------------------------+-------------------------------------
               Reporter:  milosu     |          Owner:  nobody
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  1.11
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  1
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I've discovered some obscure bug, which triggers randomly and only under
 certain circumstances, based on the address space layout.

 Try to apply attached delete_on_update_bug.py and run delete_regress
 multiple times.

 The test case should fail with:

 {{{
 ======================================================================
 FAIL: test_delete_with_custom_handlers
 (delete_regress.tests.CollectorUpdateTests)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "C:\data\django\tests\delete_regress\tests.py", line 381, in
 test_delete_with_custom_handlers
     self.assertEqual(cost_claim_in_report.threatened_id,
 t_org_in_report.pk)
 AssertionError: None != 2

 ----------------------------------------------------------------------
 Ran 19 tests in 0.970s
 }}}

 I can reproduce this bug with latest Django when I make several tweaks,
 that change the address space layout of the Python process, besides
 others:
 - use psycopg2 backend while testing instead of the dummy default
 - try to put pdb near the random shuffle
 - add somehow additional DLLs to the Python process etc.

 The issue can be fixed by applying delete_on_update_fix.diff.

 The root cause is the reuse of sql.UpdateQuery across the inner for-loop,
 due to the way update_batch is implemented (by calling add_update_values
 etc.).

 Caveats:
 The print statement in delete_on_update_bug.diff prints the order of the
 items when iterating over the field_updates dictionary.

 The order that breaks the test case is one of the following:

 organization None set([<ThreatenedOrganization: reported threatened org>])
 threatened None set([<CostClaim: cost claim>])
 organization None set([<CostClaim: reported cost claim>])

 i.e. update of "organization" fkey on <CostClaim: reported cost claim>
 must follow after the update of the "threatened" attr.

--
Ticket URL: <https://code.djangoproject.com/ticket/28099>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.a90187185d38a29393c641e51cedfe72%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to