summaryrefslogtreecommitdiff
path: root/django/db/models/sql
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/sql')
-rw-r--r--django/db/models/sql/query.py28
-rw-r--r--django/db/models/sql/where.py60
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.