﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
12247	update on empty queryset in which the update kwargs refer to inherited columns update all rows of base table	Jacob Smullyan	matiasb	"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).

{{{
#models.py

from django.db import models

# Create your models here.

class A(models.Model):
    x=models.IntegerField(default=10)

class B(models.Model):
    a=models.ForeignKey(A)
    y=models.IntegerField(default=10)

class C(models.Model):
    y=models.IntegerField(default=10)

class D(C):
    a=models.ForeignKey(A)

}}}

{{{
# tests.py
from django.test import TestCase

from models import A, B, D

class SimpleTest(TestCase):
    def setUp(self):
        self.a1=A.objects.create()
        self.a2=A.objects.create()
        for x in range(20):
            B.objects.create(a=self.a1)
            D.objects.create(a=self.a1)

    def tearDown(self):
        B.objects.all().delete()
        A.objects.all().delete()
        
        
    def test_nonempty_update(self):
        """"""
        Test that update changes that right number of rows for a nonempty queryset
        """"""
        num_updated=self.a1.b_set.update(y=100)
        self.failUnlessEqual(num_updated, 20)
        cnt=B.objects.filter(y=100).count()
        self.failUnlessEqual(cnt, 20)

    def test_empty_update(self):
        """"""
        Test that update changes that right number of rows for an empty queryset
        """"""

        num_updated=self.a2.b_set.update(y=100)
        self.failUnlessEqual(num_updated, 0)
        cnt=B.objects.filter(y=100).count()
        self.failUnlessEqual(cnt, 0)

    def test_nonempty_update_with_inheritance(self):
        """"""
        Test that update changes that right number of rows for an empty queryset
        when the update affects only a base table
        """"""

        num_updated=self.a1.d_set.update(y=100)
        self.failUnlessEqual(num_updated, 20)
        cnt=D.objects.filter(y=100).count()
        self.failUnlessEqual(cnt, 20)


    def test_empty_update_with_inheritance(self):
        """"""
        Test that update changes that right number of rows for an empty queryset
        when the update affects only a base table
        """"""

        num_updated=self.a2.d_set.update(y=100)
        self.failUnlessEqual(num_updated, 0)
        cnt=D.objects.filter(y=100).count()
        self.failUnlessEqual(cnt, 0)
}}}


"		closed	Database layer (models, ORM)	1.1		fixed			Accepted	1	0	0	0	0	0
