diff options
| author | Anssi Kääriäinen <anssi.kaariainen@thl.fi> | 2015-02-04 10:21:29 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2015-02-04 09:26:40 -0500 |
| commit | 7145c8a62a38c3b30641bb84a51f7567ce9bc10e (patch) | |
| tree | 264929e727388c6bb72cb6db45dc61b713456cc3 /django/db/models/sql | |
| parent | afe0bb7b13bb8dc4370f32225238012c873b0ee3 (diff) | |
Removed EverythingNode
At the same time, made sure that empty nodes in where clause match
everything.
Diffstat (limited to 'django/db/models/sql')
| -rw-r--r-- | django/db/models/sql/query.py | 28 | ||||
| -rw-r--r-- | django/db/models/sql/where.py | 60 |
2 files changed, 26 insertions, 62 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 719ef0f572..5335d27570 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -24,8 +24,8 @@ from django.db.models.sql.constants import (QUERY_TERMS, ORDER_DIR, SINGLE, ORDER_PATTERN, INNER, LOUTER) from django.db.models.sql.datastructures import ( EmptyResultSet, Empty, MultiJoin, Join, BaseTable) -from django.db.models.sql.where import (WhereNode, EverythingNode, - ExtraWhere, AND, OR, NothingNode) +from django.db.models.sql.where import (WhereNode, ExtraWhere, AND, OR, + NothingNode) from django.utils import six from django.utils.deprecation import RemovedInDjango20Warning from django.utils.encoding import force_text @@ -526,20 +526,8 @@ class Query(object): # Now relabel a copy of the rhs where-clause and add it to the current # one. - if rhs.where: - w = rhs.where.clone() - w.relabel_aliases(change_map) - if not self.where: - # Since 'self' matches everything, add an explicit "include - # everything" where-constraint so that connections between the - # where clauses won't exclude valid results. - self.where.add(EverythingNode(), AND) - elif self.where: - # rhs has an empty where clause. - w = self.where_class() - w.add(EverythingNode(), AND) - else: - w = self.where_class() + w = rhs.where.clone() + w.relabel_aliases(change_map) self.where.add(w, connector) # Selection columns and extra extensions are those provided by 'rhs'. @@ -1207,8 +1195,9 @@ class Query(object): # So, demotion is OK. existing_inner = set( (a for a in self.alias_map if self.alias_map[a].join_type == INNER)) - clause, require_inner = self._add_q(q_object, self.used_aliases) - self.where.add(clause, AND) + clause, _ = self._add_q(q_object, self.used_aliases) + if clause: + self.where.add(clause, AND) self.demote_joins(existing_inner) def _add_q(self, q_object, used_aliases, branch_negated=False, @@ -1233,7 +1222,8 @@ class Query(object): child, can_reuse=used_aliases, branch_negated=branch_negated, current_negated=current_negated, connector=connector, allow_joins=allow_joins) joinpromoter.add_votes(needed_inner) - target_clause.add(child_clause, connector) + if child_clause: + target_clause.add(child_clause, connector) needed_inner = joinpromoter.update_join_types(self) return target_clause, needed_inner diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index 6472c47f4f..2b04cbe708 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -28,22 +28,22 @@ class WhereNode(tree.Node): the correct SQL). A child is usually an expression producing boolean values. Most likely the - expression is a Lookup instance, but other types of objects fulfilling the - required API could be used too (for example, sql.where.EverythingNode). + expression is a Lookup instance. However, a child could also be any class with as_sql() and either - relabeled_clone() method or relabel_aliases() and clone() methods. The - second alternative should be used if the alias is not the only mutable - variable. + relabeled_clone() method or relabel_aliases() and clone() methods and + contains_aggregate attribute. """ default = AND def split_having(self, negated=False): """ Returns two possibly None nodes: one for those parts of self that - should be pushed to having and one for those parts of self - that should be in where. + should be included in the WHERE clause and one for those parts of + self that must be included in the HAVING clause. """ + if not self.contains_aggregate: + return self, None in_negated = negated ^ self.negated # If the effective connector is OR and this node contains an aggregate, # then we need to push the whole branch to HAVING clause. @@ -57,9 +57,9 @@ class WhereNode(tree.Node): for c in self.children: if hasattr(c, 'split_having'): where_part, having_part = c.split_having(in_negated) - if where_part: + if where_part is not None: where_parts.append(where_part) - if having_part: + if having_part is not None: having_parts.append(having_part) elif c.contains_aggregate: having_parts.append(c) @@ -76,55 +76,39 @@ class WhereNode(tree.Node): None, [] if this node is empty, and raises EmptyResultSet if this node can't match anything. """ - # Note that the logic here is made slightly more complex than - # necessary because there are two kind of empty nodes: Nodes - # containing 0 children, and nodes that are known to match everything. - # A match-everything node is different than empty node (which also - # technically matches everything) for backwards compatibility reasons. - # Refs #5261. result = [] result_params = [] - everything_childs, nothing_childs = 0, 0 - non_empty_childs = len(self.children) + if self.connector == AND: + full_needed, empty_needed = len(self.children), 1 + else: + full_needed, empty_needed = 1, len(self.children) for child in self.children: try: sql, params = compiler.compile(child) except EmptyResultSet: - nothing_childs += 1 + empty_needed -= 1 else: if sql: result.append(sql) result_params.extend(params) else: - if sql is None: - # Skip empty childs totally. - non_empty_childs -= 1 - continue - everything_childs += 1 + full_needed -= 1 # Check if this node matches nothing or everything. # First check the amount of full nodes and empty nodes # to make this node empty/full. - if self.connector == AND: - full_needed, empty_needed = non_empty_childs, 1 - else: - full_needed, empty_needed = 1, non_empty_childs # Now, check if this node is full/empty using the # counts. - if empty_needed - nothing_childs <= 0: + if empty_needed == 0: if self.negated: return '', [] else: raise EmptyResultSet - if full_needed - everything_childs <= 0: + if full_needed == 0: if self.negated: raise EmptyResultSet else: return '', [] - - if non_empty_childs == 0: - # All the child nodes were empty, so this one is empty, too. - return None, [] conn = ' %s ' % self.connector sql_string = conn.join(result) if sql_string: @@ -186,16 +170,6 @@ class WhereNode(tree.Node): return self._contains_aggregate(self) -class EverythingNode(object): - """ - A node that matches everything. - """ - contains_aggregate = False - - def as_sql(self, compiler=None, connection=None): - return '', [] - - class NothingNode(object): """ A node that matches nothing. |
