diff options
| author | Anssi Kääriäinen <akaariai@gmail.com> | 2014-01-08 19:35:47 +0200 |
|---|---|---|
| committer | Anssi Kääriäinen <akaariai@gmail.com> | 2014-02-04 19:06:37 +0200 |
| commit | fd3fa851b592700a8b04af46f626454db0db02e4 (patch) | |
| tree | d26538d93939d45c162da265dfe03a0accfa6fc0 /django | |
| parent | 0f272629ca18e440aef67b4a3fd9377a57fb25a8 (diff) | |
[1.6.x] Fixed #21748 -- join promotion for negated AND conditions
Made sure Django treats case .filter(NOT (a AND b)) the same way as
.filter((NOT a OR NOT b)) for join promotion.
Heavily modified backpatch of 35cecb1ebd0ccda0be7a518d1b7273333d26fbae
from master.
Conflicts:
django/db/models/sql/query.py
tests/queries/tests.py
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/models/sql/query.py | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index bb05c94e14..7868c19ab8 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1211,16 +1211,18 @@ class Query(object): connector = q_object.connector current_negated = current_negated ^ q_object.negated branch_negated = branch_negated or q_object.negated - # Note that if the connector happens to match what we have already in - # the tree, the add will be a no-op. target_clause = self.where_class(connector=connector, negated=q_object.negated) - - if connector == OR: + # Treat case NOT (a AND b) like case ((NOT a) OR (NOT b)) for join + # promotion. See ticket #21748. + effective_connector = connector + if current_negated: + effective_connector = OR if effective_connector == AND else AND + if effective_connector == OR: alias_usage_counts = dict() aliases_before = set(self.tables) for child in q_object.children: - if connector == OR: + if effective_connector == OR: refcounts_before = self.alias_refcount.copy() if isinstance(child, Node): child_clause = self._add_q( @@ -1231,11 +1233,11 @@ class Query(object): child, can_reuse=used_aliases, branch_negated=branch_negated, current_negated=current_negated) target_clause.add(child_clause, connector) - if connector == OR: + if effective_connector == OR: used = alias_diff(refcounts_before, self.alias_refcount) for alias in used: alias_usage_counts[alias] = alias_usage_counts.get(alias, 0) + 1 - if connector == OR: + if effective_connector == OR: self.promote_disjunction(aliases_before, alias_usage_counts, len(q_object.children)) return target_clause |
