#34840: Django 4.2 casts text fields when testing IS NULL, preventing use of
partial indexes
-------------------------------------+-------------------------------------
     Reporter:  Alex Vandiver        |                    Owner:  Mariusz
                                     |  Felisiak
         Type:  Bug                  |                   Status:  assigned
    Component:  Database layer       |                  Version:  4.2
  (models, ORM)                      |
     Severity:  Release blocker      |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

 * owner:  murtatah => Mariusz Felisiak


Comment:

 I wonder if we could extend Simon's solution for #34754
 (3434dbd39d373df7193ad006b970c09c1a909ea3). The following patch passes all
 tests (with and without server side binding parameters):
 {{{#!diff
 diff --git a/django/db/backends/postgresql/operations.py
 b/django/db/backends/postgresql/operations.py
 index 93eb982f4b..e536681914 100644
 --- a/django/db/backends/postgresql/operations.py
 +++ b/django/db/backends/postgresql/operations.py
 @@ -155,13 +155,6 @@ class DatabaseOperations(BaseDatabaseOperations):
      def lookup_cast(self, lookup_type, internal_type=None):
          lookup = "%s"

 -        if lookup_type == "isnull" and internal_type in (
 -            "CharField",
 -            "EmailField",
 -            "TextField",
 -        ):
 -            return "%s::text"
 -
          # Cast text lookups to text to allow things like
 filter(x__contains=4)
          if lookup_type in (
              "iexact",
 diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py
 index 896d3eee44..eb887f5548 100644
 --- a/django/db/models/lookups.py
 +++ b/django/db/models/lookups.py
 @@ -624,11 +624,17 @@ class IsNull(BuiltinLookup):
              raise ValueError(
                  "The QuerySet value for an isnull lookup must be True or
 False."
              )
 -        if isinstance(self.lhs, Value) and self.lhs.value is None:
 +        if isinstance(self.lhs, Value):
              if self.rhs:
 -                raise FullResultSet
 +                if self.lhs.value is None:
 +                    raise FullResultSet
 +                else:
 +                    raise EmptyResultSet
              else:
 -                raise EmptyResultSet
 +                if self.lhs.value is None:
 +                    raise EmptyResultSet
 +                else:
 +                    raise FullResultSet
          sql, params = self.process_lhs(compiler, connection)
          if self.rhs:
              return "%s IS NULL" % sql, params
 diff --git a/django/db/models/query_utils.py
 b/django/db/models/query_utils.py
 index 4f3358eb8d..830a7fdb6f 100644
 --- a/django/db/models/query_utils.py
 +++ b/django/db/models/query_utils.py
 @@ -10,7 +10,7 @@ import inspect
  import logging
  from collections import namedtuple

 -from django.core.exceptions import FieldError
 +from django.core.exceptions import EmptyResultSet, FieldError
  from django.db import DEFAULT_DB_ALIAS, DatabaseError, connections
  from django.db.models.constants import LOOKUP_SEP
  from django.utils import tree
 @@ -140,6 +140,8 @@ class Q(tree.Node):
          except DatabaseError as e:
              logger.warning("Got a database error calling check() on %r:
 %s", self, e)
              return True
 +        except EmptyResultSet:
 +            return False

      def deconstruct(self):
          path = "%s.%s" % (self.__class__.__module__,
 self.__class__.__name__)

 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34840#comment:16>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018aac965e91-0d765c1b-bbaa-45cd-b1b3-621de4e7016d-000000%40eu-central-1.amazonses.com.

Reply via email to