summaryrefslogtreecommitdiff
path: root/django/db/models/sql
diff options
context:
space:
mode:
authorIan Foote <python@ian.feete.org>2021-04-02 18:25:20 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-07-09 11:43:06 +0200
commitf42ccdd835e5b3f0914b5e6f87621c648136ea36 (patch)
tree49f0a1ecbd05b4d8d0049cec21ad564a663b427f /django/db/models/sql
parentf5dccbafb957841d0867f0b153d7f7123f0ec83d (diff)
Fixed #27021 -- Allowed lookup expressions in annotations, aggregations, and QuerySet.filter().
Thanks Hannes Ljungberg and Simon Charette for reviews. Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
Diffstat (limited to 'django/db/models/sql')
-rw-r--r--django/db/models/sql/query.py6
-rw-r--r--django/db/models/sql/where.py19
2 files changed, 22 insertions, 3 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 87be8ea9f0..2412e6ad4e 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1262,9 +1262,9 @@ class Query(BaseExpression):
if hasattr(filter_expr, 'resolve_expression'):
if not getattr(filter_expr, 'conditional', False):
raise TypeError('Cannot filter against a non-conditional expression.')
- condition = self.build_lookup(
- ['exact'], filter_expr.resolve_expression(self, allow_joins=allow_joins), True
- )
+ condition = filter_expr.resolve_expression(self, allow_joins=allow_joins)
+ if not isinstance(condition, Lookup):
+ condition = self.build_lookup(['exact'], condition, True)
clause = self.where_class()
clause.add(condition, AND)
return clause, []
diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
index 2577e1d7a5..5a4da97396 100644
--- a/django/db/models/sql/where.py
+++ b/django/db/models/sql/where.py
@@ -208,6 +208,25 @@ class WhereNode(tree.Node):
clone.resolved = True
return clone
+ @cached_property
+ def output_field(self):
+ from django.db.models import BooleanField
+ return BooleanField()
+
+ def select_format(self, compiler, sql, params):
+ # Wrap filters with a CASE WHEN expression if a database backend
+ # (e.g. Oracle) doesn't support boolean expression in SELECT or GROUP
+ # BY list.
+ if not compiler.connection.features.supports_boolean_expr_in_select_clause:
+ sql = f'CASE WHEN {sql} THEN 1 ELSE 0 END'
+ return sql, params
+
+ def get_db_converters(self, connection):
+ return self.output_field.get_db_converters(connection)
+
+ def get_lookup(self, lookup):
+ return self.output_field.get_lookup(lookup)
+
class NothingNode:
"""A node that matches nothing."""