Django

Code

Changeset 7496

Show
Ignore:
Timestamp:
04/28/08 06:51:52 (2 months ago)
Author:
mtredinnick
Message:

Made some types of nested update queries very slightly more efficient at the
database level. Also worked around the fact that MySQL (and maybe other
backends we don't know about) cannot select from the table they're updating.

Fixed #7095.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/backends/__init__.py

    r7477 r7496  
    5252    uses_custom_query_class = False 
    5353    empty_fetchmany_value = [] 
     54    update_can_self_select = True 
    5455 
    5556class BaseDatabaseOperations(object): 
  • django/trunk/django/db/backends/mysql/base.py

    r7477 r7496  
    6464    inline_fk_references = False 
    6565    empty_fetchmany_value = () 
     66    update_can_self_select = False 
    6667 
    6768class DatabaseOperations(BaseDatabaseOperations): 
  • django/trunk/django/db/backends/mysql_old/base.py

    r7477 r7496  
    6868    inline_fk_references = False 
    6969    empty_fetchmany_value = () 
     70    update_can_self_select = False 
    7071 
    7172class DatabaseOperations(BaseDatabaseOperations): 
  • django/trunk/django/db/models/sql/subqueries.py

    r7488 r7496  
    160160        query = self.clone(klass=Query) 
    161161        query.bump_prefix() 
    162         query.select = [] 
    163162        query.extra_select = {} 
    164         query.add_fields([query.model._meta.pk.name]) 
     163        first_table = query.tables[0] 
     164        if query.alias_refcount[first_table] == 1: 
     165            # We can remove one table from the inner query. 
     166            query.unref_alias(first_table) 
     167            for i in xrange(1, len(query.tables)): 
     168                table = query.tables[i] 
     169                if query.alias_refcount[table]: 
     170                    break 
     171            join_info = query.alias_map[table] 
     172            query.select = [(join_info[RHS_ALIAS], join_info[RHS_JOIN_COL])] 
     173            must_pre_select = False 
     174        else: 
     175            query.select = [] 
     176            query.add_fields([query.model._meta.pk.name]) 
     177            must_pre_select = not self.connection.features.update_can_self_select 
    165178 
    166179        # Now we adjust the current query: reset the where clause and get rid 
    167180        # of all the tables we don't need (since they're in the sub-select). 
    168181        self.where = self.where_class() 
    169         if self.related_updates: 
     182        if self.related_updates or must_pre_select: 
     183            # Either we're using the idents in multiple update queries (so 
     184            # don't want them to change), or the db backend doesn't support 
     185            # selecting from the updating table (e.g. MySQL). 
    170186            idents = [] 
    171187            for rows in query.execute_sql(MULTI): 
     
    174190            self.related_ids = idents 
    175191        else: 
     192            # The fast path. Filters and updates in one query. 
    176193            self.add_filter(('pk__in', query)) 
    177194        for alias in self.tables[1:]: