diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 61fd2be..4a06c6b 100644
a
|
b
|
class Query(object):
|
254 | 254 | obj.dupe_avoidance = self.dupe_avoidance.copy() |
255 | 255 | obj.select = self.select[:] |
256 | 256 | obj.tables = self.tables[:] |
257 | | obj.where = copy.deepcopy(self.where, memo=memo) |
| 257 | try: |
| 258 | obj.where = self.where.clone() |
| 259 | except AttributeError: |
| 260 | obj.where = copy.deepcopy(self.where, memo=memo) |
258 | 261 | obj.where_class = self.where_class |
259 | 262 | if self.group_by is None: |
260 | 263 | obj.group_by = None |
261 | 264 | else: |
262 | 265 | obj.group_by = self.group_by[:] |
263 | | obj.having = copy.deepcopy(self.having, memo=memo) |
| 266 | try: |
| 267 | obj.having = self.having.clone() |
| 268 | except AttributeError: |
| 269 | obj.having = copy.deepcopy(self.having, memo=memo) |
264 | 270 | obj.order_by = self.order_by[:] |
265 | 271 | obj.low_mark, obj.high_mark = self.low_mark, self.high_mark |
266 | 272 | obj.distinct = self.distinct |
diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
index 3e9dbf0..eee8235 100644
a
|
b
|
class EverythingNode(object):
|
260 | 260 | def relabel_aliases(self, change_map, node=None): |
261 | 261 | return |
262 | 262 | |
| 263 | def clone(self): |
| 264 | return self |
| 265 | |
263 | 266 | class NothingNode(object): |
264 | 267 | """ |
265 | 268 | A node that matches nothing. |
… |
… |
class NothingNode(object):
|
270 | 273 | def relabel_aliases(self, change_map, node=None): |
271 | 274 | return |
272 | 275 | |
| 276 | def clone(self): |
| 277 | return self |
| 278 | |
273 | 279 | class ExtraWhere(object): |
274 | 280 | def __init__(self, sqls, params): |
275 | 281 | self.sqls = sqls |
… |
… |
class ExtraWhere(object):
|
278 | 284 | def as_sql(self, qn=None, connection=None): |
279 | 285 | return " AND ".join(self.sqls), tuple(self.params or ()) |
280 | 286 | |
| 287 | def clone(self): |
| 288 | return self |
| 289 | |
281 | 290 | class Constraint(object): |
282 | 291 | """ |
283 | 292 | An object that can be passed to WhereNode.add() and knows how to |
… |
… |
class Constraint(object):
|
342 | 351 | def relabel_aliases(self, change_map): |
343 | 352 | if self.alias in change_map: |
344 | 353 | self.alias = change_map[self.alias] |
| 354 | |
| 355 | def clone(self): |
| 356 | return Constraint(self.alias, self.col, self.field) |
diff --git a/django/utils/tree.py b/django/utils/tree.py
index 36b5977..3ef96e0 100644
a
|
b
|
class Node(object):
|
45 | 45 | return obj |
46 | 46 | _new_instance = classmethod(_new_instance) |
47 | 47 | |
| 48 | def clone(self): |
| 49 | clone = self.__class__._new_instance( |
| 50 | children=[], connector=self.connector, negated=self.negated) |
| 51 | for child in self.children: |
| 52 | if isinstance(child, tuple): |
| 53 | clone.children.append( |
| 54 | (child[0].clone(), child[1], child[2], child[3])) |
| 55 | else: |
| 56 | try: |
| 57 | clone.children.append(child.clone()) |
| 58 | except AttributeError: |
| 59 | # backwards compatibility - raise deprecation warning? |
| 60 | clone.children.append(copy.deepcopy(child)) |
| 61 | for parent in self.subtree_parents: |
| 62 | try: |
| 63 | clone.subtree_parents.append(parent.clone()) |
| 64 | except AttributeError: |
| 65 | clone.subtree_parents.append(copy.deepcopy(parent)) |
| 66 | return clone |
| 67 | |
48 | 68 | def __str__(self): |
49 | 69 | if self.negated: |
50 | 70 | return '(NOT (%s: %s))' % (self.connector, ', '.join([str(c) for c |