Description

A queryset that happens to return nothing if evaluated, when updated, may erroneously update all rows if the queryset refers to an inherited model and the update columns are in the base table. I'm testing with django 1.1.X on rev 11752. This is a bug with potentially very serious consequences. (Note: I believe this bug to be distinct, although similar in its effects, to #12142.)

Here is test code to produce the problem. One of the below tests will fail (test_empty_update_with_inheritance).

After long debugging to find the issue, added patch to manage empty related_ids when building related_updates queries.
Thanks to nessita for the previous debugging info and jsmullyan for the provided tests.

The patch looks pretty good, and seems to fix the problem, but I wonder if the bug isn't another level down. This seems to be triggered when self.related_ids is [], so we're essentially calling query.add_filter(('pk__in', [])). It seems like pk__in=[] should essentially be a no-op, but it sounds like it's actually selecting everything.

@jkocherhans - add_filter(pkin=[]) *is* a no-op (or rather, it raises EmptyResultSet). The issue here is that the "if self.related_ids" condition means that you *aren't* adding the [] filter, which means that you are left with a default "update everything" filter. Changing the condition to "if self.related_ids is None" means that the [] filter will be added, and thereby shortcut the update into a no-op.

(In [12911]) [1.1.X] Fixed #12247 -- Corrected the way update queries are processed when the update only refers to attributes on a base class. Thanks to jsmullyan for the report, and matiasb for the fix.