Skip to content

Commit f1390aa

Browse files
committed
Push any pushable lookup
1 parent 6e92b2b commit f1390aa

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

django_mongodb_backend/compiler.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from django.db.models.sql import compiler
1414
from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE, MULTI, SINGLE
1515
from django.db.models.sql.datastructures import BaseTable
16-
from django.db.models.sql.where import AND, OR, XOR, WhereNode
16+
from django.db.models.sql.where import AND, OR, XOR, NothingNode, WhereNode
1717
from django.utils.functional import cached_property
1818
from pymongo import ASCENDING, DESCENDING
1919

@@ -660,34 +660,41 @@ def get_combinator_queries(self):
660660

661661
def _get_pushable_conditions(self):
662662
def collect_pushable(expr, negated=False):
663+
if isinstance(expr, NothingNode):
664+
return {}
663665
if isinstance(expr, WhereNode):
664-
pushable_expressions = (
665-
collect_pushable(sub_expr, negated=negated != expr.negated)
666-
for sub_expr in expr.children
667-
)
666+
negated = negated != expr.negated
667+
pushable_expressions = [
668+
collect_pushable(sub_expr, negated=negated) for sub_expr in expr.children
669+
]
668670
operator = expr.connector
669671
if operator == XOR:
670672
return {}
671673
if negated:
672674
operator = OR if operator == AND else AND
673-
result = next(pushable_expressions, {})
674-
shared_alias = set(result)
675+
alias_children = defaultdict(list)
676+
shared_alias = None
677+
result = {}
675678
for pe in pushable_expressions:
676-
shared_alias &= set(pe)
679+
if not shared_alias:
680+
shared_alias = set(pe)
681+
else:
682+
shared_alias &= set(pe)
677683
for alias, expressions in pe.items():
678-
children = [expressions]
679-
if alias in result:
680-
children.append(result[alias])
681-
result[alias] = WhereNode(
682-
children=children,
683-
negated=negated,
684-
connector=operator,
685-
)
684+
alias_children[alias].append(expressions)
685+
for alias, children in alias_children.items():
686+
result[alias] = WhereNode(
687+
children=children,
688+
negated=False,
689+
connector=operator,
690+
)
686691
if operator == AND:
687692
return result
688693
return {k: v for k, v in result.items() if k in shared_alias}
689-
if expr.lhs.is_simple_column and (
690-
is_constant_value(expr.rhs) or expr.rhs.is_simple_column
694+
if (
695+
expr is not None
696+
and isinstance(expr.lhs, Col)
697+
and (is_constant_value(expr.rhs) or getattr(expr.rhs, "is_simple_column", False))
691698
):
692699
alias = expr.lhs.alias
693700
expr = WhereNode(children=[expr], negated=negated)

django_mongodb_backend/query_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.core.exceptions import FullResultSet
2+
from django.db.models import F
23
from django.db.models.aggregates import Aggregate
34
from django.db.models.expressions import CombinedExpression, Func, Value
45
from django.db.models.sql.query import Query
@@ -67,7 +68,7 @@ def is_constant_value(value):
6768
else:
6869
constants_sub_expressions = True
6970
constants_sub_expressions = constants_sub_expressions and not (
70-
isinstance(value, Query)
71+
isinstance(value, Query | F)
7172
or value.contains_aggregate
7273
or value.contains_over_clause
7374
or value.contains_column_references

0 commit comments

Comments
 (0)