Ticket #9848: filtered_update_fix.diff

File filtered_update_fix.diff, 3.2 KB (added by Jamie Gennis, 7 years ago)
  • django/db/models/sql/subqueries.py

     
    170170        query.extra_select = {}
    171171        first_table = query.tables[0]
    172172        if query.alias_refcount[first_table] == 1:
    173             # We can remove one table from the inner query.
     173            # We can remove one table from the inner query.  Because the
     174            # sub-select isn't selecting anything from the table being updated,
     175            # the where clause may need to filter based on a foreign key being
     176            # in the sub-select rather than its own primary key.
    174177            query.unref_alias(first_table)
    175178            for i in xrange(1, len(query.tables)):
    176179                table = query.tables[i]
     
    178181                    break
    179182            join_info = query.alias_map[table]
    180183            query.select = [(join_info[RHS_ALIAS], join_info[RHS_JOIN_COL])]
     184            for field in query.model._meta.fields:
     185                if field.column == join_info[LHS_JOIN_COL]:
     186                    # field is either a ForeignKey field refering to table or
     187                    # the primary key of query.model.
     188                    where_filter = '%s__in' % field.name
     189                    break
    181190            must_pre_select = False
    182191        else:
    183192            query.select = []
    184193            query.add_fields([query.model._meta.pk.name])
     194            where_filter = 'pk__in'
    185195            must_pre_select = not self.connection.features.update_can_self_select
    186196
    187197        # Now we adjust the current query: reset the where clause and get rid
     
    194204            idents = []
    195205            for rows in query.execute_sql(MULTI):
    196206                idents.extend([r[0] for r in rows])
    197             self.add_filter(('pk__in', idents))
     207            self.add_filter((where_filter, idents))
    198208            self.related_ids = idents
    199209        else:
    200210            # The fast path. Filters and updates in one query.
    201             self.add_filter(('pk__in', query))
     211            self.add_filter((where_filter, query))
    202212        for alias in self.tables[1:]:
    203213            self.alias_refcount[alias] = 0
    204214
  • tests/regressiontests/queries/models.py

     
    10211021# optimise the inner query without losing results.
    10221022>>> Annotation.objects.exclude(tag__children__name="t2")
    10231023[<Annotation: a2>]
     1024
     1025# Bug #9848
     1026# This is a little tricky to test because we have to make sure that the IDs
     1027# from different tables don't happen to match.
     1028>>> Ranking.objects.filter(author__name='a1')
     1029[<Ranking: 3: a1>]
     1030>>> Ranking.objects.filter(author__name='a1').update(rank='4')
     10311
     1032>>> r = Ranking.objects.filter(author__name='a1')[0]
     1033>>> r.id
     10343
     1035>>> r.author.id
     10361
     1037>>> r.rank
     10384
     1039>>> r.rank = 3
     1040>>> r.save()
     1041>>> Ranking.objects.all()
     1042[<Ranking: 3: a1>, <Ranking: 2: a2>, <Ranking: 1: a3>]
    10241043"""}
    10251044
    10261045# In Python 2.3 and the Python 2.6 beta releases, exceptions raised in __len__
Back to Top