Fixed #36821 -- Treated empty strings as NULL for iexact lookups on Oracle.

Signed-off-by: JaeHyuck Sa <wogur981208@gmail.com>
This commit is contained in:
JaeHyuck Sa
2026-01-15 00:09:14 +09:00
committed by Jacob Walls
parent 6a596373d4
commit 4ce4ed72a4
3 changed files with 15 additions and 3 deletions

View File

@@ -1444,7 +1444,7 @@ class Query(BaseExpression):
# DEFAULT_DB_ALIAS isn't nice but it's the best that can be done here.
# A similar thing is done in is_nullable(), too.
if (
lookup_name == "exact"
lookup_name in ("exact", "iexact")
and lookup.rhs == ""
and connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls
):

View File

@@ -7,7 +7,7 @@ class Poll(models.Model):
class Choice(models.Model):
poll = models.ForeignKey(Poll, models.CASCADE)
choice = models.CharField(max_length=200)
choice = models.CharField(max_length=200, null=True)
# A set of models with an inner one pointing to two outer ones.

View File

@@ -1,5 +1,5 @@
from django.core.exceptions import FieldError
from django.test import TestCase
from django.test import TestCase, skipUnlessDBFeature
from .models import Choice, Inner, OuterA, OuterB, Poll
@@ -44,6 +44,18 @@ class NullQueriesTests(TestCase):
with self.assertRaisesMessage(ValueError, "Cannot use None as a query value"):
Choice.objects.filter(id__gt=None)
@skipUnlessDBFeature("interprets_empty_strings_as_nulls")
def test_empty_string_is_null(self):
p = Poll.objects.create(question="?")
c1 = Choice.objects.create(poll=p, choice=None)
c2 = Choice.objects.create(poll=p, choice="")
cases = [{"choice__exact": ""}, {"choice__iexact": ""}]
for lookup in cases:
with self.subTest(lookup):
self.assertSequenceEqual(
Choice.objects.filter(**lookup).order_by("id"), [c1, c2]
)
def test_unsaved(self):
poll = Poll(question="How?")
msg = (