فهرست منبع

Refs #25367 -- Moved conditional expression wrapping to the Exact lookup.

Simon Charette 5 سال پیش
والد
کامیت
37e6c5b79b
3فایلهای تغییر یافته به همراه19 افزوده شده و 10 حذف شده
  1. 4 4
      django/db/backends/oracle/operations.py
  2. 14 0
      django/db/models/lookups.py
  3. 1 6
      django/db/models/sql/query.py

+ 4 - 4
django/db/backends/oracle/operations.py

@@ -6,7 +6,7 @@ from django.conf import settings
 from django.db.backends.base.operations import BaseDatabaseOperations
 from django.db.backends.utils import strip_quotes, truncate_name
 from django.db.models.expressions import Exists, ExpressionWrapper, RawSQL
-from django.db.models.query_utils import Q
+from django.db.models.sql.where import WhereNode
 from django.db.utils import DatabaseError
 from django.utils import timezone
 from django.utils.encoding import force_bytes, force_str
@@ -633,10 +633,10 @@ END;
         Oracle supports only EXISTS(...) or filters in the WHERE clause, others
         must be compared with True.
         """
-        if isinstance(expression, Exists):
-            return True
-        if isinstance(expression, ExpressionWrapper) and isinstance(expression.expression, Q):
+        if isinstance(expression, (Exists, WhereNode)):
             return True
+        if isinstance(expression, ExpressionWrapper) and expression.conditional:
+            return self.conditional_expression_supported_in_where_clause(expression.expression)
         if isinstance(expression, RawSQL) and expression.conditional:
             return True
         return False

+ 14 - 0
django/db/models/lookups.py

@@ -274,6 +274,20 @@ class Exact(FieldGetDbPrepValueMixin, BuiltinLookup):
                 )
         return super().process_rhs(compiler, connection)
 
+    def as_sql(self, compiler, connection):
+        # Avoid comparison against direct rhs if lhs is a boolean value. That
+        # turns "boolfield__exact=True" into "WHERE boolean_field" instead of
+        # "WHERE boolean_field = True" when allowed.
+        if (
+            isinstance(self.rhs, bool) and
+            getattr(self.lhs, 'conditional', False) and
+            connection.ops.conditional_expression_supported_in_where_clause(self.lhs)
+        ):
+            lhs_sql, params = self.process_lhs(compiler, connection)
+            template = '%s' if self.rhs else 'NOT %s'
+            return template % lhs_sql, params
+        return super().as_sql(compiler, connection)
+
 
 @Field.register_lookup
 class IExact(BuiltinLookup):

+ 1 - 6
django/db/models/sql/query.py

@@ -1222,12 +1222,7 @@ class Query(BaseExpression):
         if isinstance(filter_expr, dict):
             raise FieldError("Cannot parse keyword query as dict")
         if hasattr(filter_expr, 'resolve_expression') and getattr(filter_expr, 'conditional', False):
-            if connections[DEFAULT_DB_ALIAS].ops.conditional_expression_supported_in_where_clause(filter_expr):
-                condition = filter_expr.resolve_expression(self)
-            else:
-                # Expression is not supported in the WHERE clause, add
-                # comparison with True.
-                condition = self.build_lookup(['exact'], filter_expr.resolve_expression(self), True)
+            condition = self.build_lookup(['exact'], filter_expr.resolve_expression(self), True)
             clause = self.where_class()
             clause.add(condition, AND)
             return clause, []