Ticket #16759: 16759_where_clone_2.diff

File 16759_where_clone_2.diff, 5.9 KB (added by akaariai, 3 years ago)

Latest cleanup of wherenode cloning

  • django/db/models/sql/aggregates.py

    diff --git a/django/db/models/sql/aggregates.py b/django/db/models/sql/aggregates.py
    index 207bc0c..7328660 100644
    a b  
    11"""
    22Classes to represent the default SQL aggregate functions
    33"""
     4import copy
    45
    56class AggregateField(object):
    67    """An internal field mockup used to identify aggregates in the
    class Aggregate(object): 
    6970
    7071        self.field = tmp
    7172
     73    def clone(self):
     74        # Different aggregates have different init methods, so use copy here
     75        # deepcopy is not needed, as self.col is only changing variable.
     76        return copy.copy(self)
     77
    7278    def relabel_aliases(self, change_map):
    7379        if isinstance(self.col, (list, tuple)):
    7480            self.col = (change_map.get(self.col[0], self.col[0]), self.col[1])
  • django/db/models/sql/query.py

    diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
    index ed2bc06..b669673 100644
    a b class Query(object): 
    256256        obj.dupe_avoidance = self.dupe_avoidance.copy()
    257257        obj.select = self.select[:]
    258258        obj.tables = self.tables[:]
    259         obj.where = copy.deepcopy(self.where, memo=memo)
     259        obj.where = self.where.clone()
    260260        obj.where_class = self.where_class
    261261        if self.group_by is None:
    262262            obj.group_by = None
    263263        else:
    264264            obj.group_by = self.group_by[:]
    265         obj.having = copy.deepcopy(self.having, memo=memo)
     265        obj.having = self.having.clone()
    266266        obj.order_by = self.order_by[:]
    267267        obj.low_mark, obj.high_mark = self.low_mark, self.high_mark
    268268        obj.distinct = self.distinct
    class Query(object): 
    271271        obj.select_for_update_nowait = self.select_for_update_nowait
    272272        obj.select_related = self.select_related
    273273        obj.related_select_cols = []
    274         obj.aggregates = copy.deepcopy(self.aggregates, memo=memo)
     274        obj.aggregates = SortedDict((k, v.clone())
     275                                    for k, v in self.aggregates.items())
    275276        if self.aggregate_select_mask is None:
    276277            obj.aggregate_select_mask = None
    277278        else:
    class Query(object): 
    294295            obj._extra_select_cache = self._extra_select_cache.copy()
    295296        obj.extra_tables = self.extra_tables
    296297        obj.extra_order_by = self.extra_order_by
    297         obj.deferred_loading = copy.deepcopy(self.deferred_loading, memo=memo)
     298        obj.deferred_loading = copy.copy(self.deferred_loading[0]), self.deferred_loading[1]
    298299        if self.filter_is_sticky and self.used_aliases:
    299300            obj.used_aliases = self.used_aliases.copy()
    300301        else:
    class Query(object): 
    508509        # Now relabel a copy of the rhs where-clause and add it to the current
    509510        # one.
    510511        if rhs.where:
    511             w = copy.deepcopy(rhs.where)
     512            w = rhs.where.clone()
    512513            w.relabel_aliases(change_map)
    513514            if not self.where:
    514515                # Since 'self' matches everything, add an explicit "include
    class Query(object): 
    529530            if isinstance(col, (list, tuple)):
    530531                self.select.append((change_map.get(col[0], col[0]), col[1]))
    531532            else:
    532                 item = copy.deepcopy(col)
     533                item = col.clone()
    533534                item.relabel_aliases(change_map)
    534535                self.select.append(item)
    535536        self.select_fields = rhs.select_fields[:]
  • django/db/models/sql/where.py

    diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
    index 1455ba6..bcf0c3b 100644
    a b class EverythingNode(object): 
    263263    def relabel_aliases(self, change_map, node=None):
    264264        return
    265265
     266    def clone(self):
     267        return self
     268
    266269class NothingNode(object):
    267270    """
    268271    A node that matches nothing.
    class NothingNode(object): 
    273276    def relabel_aliases(self, change_map, node=None):
    274277        return
    275278
     279    def clone(self):
     280        return self
     281
    276282class ExtraWhere(object):
    277283    def __init__(self, sqls, params):
    278284        self.sqls = sqls
    class ExtraWhere(object): 
    281287    def as_sql(self, qn=None, connection=None):
    282288        return " AND ".join(self.sqls), tuple(self.params or ())
    283289
     290    def clone(self):
     291        return self
     292
    284293class Constraint(object):
    285294    """
    286295    An object that can be passed to WhereNode.add() and knows how to
    class Constraint(object): 
    345354    def relabel_aliases(self, change_map):
    346355        if self.alias in change_map:
    347356            self.alias = change_map[self.alias]
     357
     358    def clone(self):
     359        return Constraint(self.alias, self.col, self.field)
  • django/utils/tree.py

    diff --git a/django/utils/tree.py b/django/utils/tree.py
    index 36b5977..758bc46 100644
    a b class Node(object): 
    4545        return obj
    4646    _new_instance = classmethod(_new_instance)
    4747
     48    def clone(self):
     49        """
     50        Creates a clone of the tree. Must only be called on root nodes (nodes
     51        with empty subtree_parents).
     52        """
     53        assert not self.subtree_parents, '.clone() can only be called on root nodes'
     54        clone = self.__class__._new_instance(
     55            children=[], connector=self.connector, negated=self.negated)
     56        for child in self.children:
     57            # A pretty bad abstraction leak: the "tuple" child is a special
     58            # child type used in querysets. Querysets should instead define
     59            # a leafnode which does the two lines below the check. (TODO).
     60            if isinstance(child, tuple):
     61                clone.children.append(
     62                    (child[0].clone(), child[1], child[2], child[3]))
     63            else:
     64                clone.children.append(child.clone())
     65        return clone
     66
    4867    def __str__(self):
    4968        if self.negated:
    5069            return '(NOT (%s: %s))' % (self.connector, ', '.join([str(c) for c
Back to Top