1
0
mirror of https://github.com/django/django.git synced 2024-12-22 09:05:43 +00:00

Fixed #34544 -- Avoided DBMS_LOB.SUBSTR() wrapping with IS NULL condition on Oracle.

Regression in 09ffc5c121.

Thanks Michael Smith for the report.

This also reverts commit 1e4da43955.
This commit is contained in:
Mariusz Felisiak 2023-05-08 19:34:30 +02:00 committed by GitHub
parent aaf8c76c56
commit 1586a09b79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 18 additions and 20 deletions

View File

@ -296,12 +296,6 @@ END;
columns.append(value[0]) columns.append(value[0])
return tuple(columns) return tuple(columns)
def field_cast_sql(self, db_type, internal_type):
if db_type and db_type.endswith("LOB") and internal_type != "JSONField":
return "DBMS_LOB.SUBSTR(%s)"
else:
return "%s"
def no_limit_value(self): def no_limit_value(self):
return None return None
@ -344,7 +338,9 @@ END;
def lookup_cast(self, lookup_type, internal_type=None): def lookup_cast(self, lookup_type, internal_type=None):
if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"): if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"):
return "UPPER(%s)" return "UPPER(%s)"
if internal_type == "JSONField" and lookup_type == "exact": if (
lookup_type != "isnull" and internal_type in ("BinaryField", "TextField")
) or (lookup_type == "exact" and internal_type == "JSONField"):
return "DBMS_LOB.SUBSTR(%s)" return "DBMS_LOB.SUBSTR(%s)"
return "%s" return "%s"

View File

@ -82,6 +82,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
"indexes.tests.SchemaIndexesNotPostgreSQLTests." "indexes.tests.SchemaIndexesNotPostgreSQLTests."
"test_create_index_ignores_opclasses", "test_create_index_ignores_opclasses",
}, },
"PostgreSQL requires casting to text.": {
"lookup.tests.LookupTests.test_textfield_exact_null",
},
} }
@cached_property @cached_property

View File

@ -9,4 +9,6 @@ Django 4.2.2 fixes several bugs in 4.2.1.
Bugfixes Bugfixes
======== ========
* ... * Fixed a regression in Django 4.2 that caused an unnecessary
``DBMS_LOB.SUBSTR()`` wrapping in the ``__isnull`` and ``__exact=None``
lookups for ``TextField()``/``BinaryField()`` on Oracle (:ticket:`34544`).

View File

@ -19,6 +19,7 @@ class Alarm(models.Model):
class Author(models.Model): class Author(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
alias = models.CharField(max_length=50, null=True, blank=True) alias = models.CharField(max_length=50, null=True, blank=True)
bio = models.TextField(null=True)
class Meta: class Meta:
ordering = ("name",) ordering = ("name",)
@ -50,22 +51,11 @@ class NulledTextField(models.TextField):
return None if value == "" else value return None if value == "" else value
class NullField(models.Field):
pass
NullField.register_lookup(IsNull)
@NulledTextField.register_lookup @NulledTextField.register_lookup
class NulledTransform(models.Transform): class NulledTransform(models.Transform):
lookup_name = "nulled" lookup_name = "nulled"
template = "NULL" template = "NULL"
@property
def output_field(self):
return NullField()
@NulledTextField.register_lookup @NulledTextField.register_lookup
class IsNullWithNoneAsRHS(IsNull): class IsNullWithNoneAsRHS(IsNull):

View File

@ -49,7 +49,7 @@ class LookupTests(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
# Create a few Authors. # Create a few Authors.
cls.au1 = Author.objects.create(name="Author 1", alias="a1") cls.au1 = Author.objects.create(name="Author 1", alias="a1", bio="x" * 4001)
cls.au2 = Author.objects.create(name="Author 2", alias="a2") cls.au2 = Author.objects.create(name="Author 2", alias="a2")
# Create a few Articles. # Create a few Articles.
cls.a1 = Article.objects.create( cls.a1 = Article.objects.create(
@ -1029,6 +1029,13 @@ class LookupTests(TestCase):
Season.objects.create(year=2012, gt=None) Season.objects.create(year=2012, gt=None)
self.assertQuerySetEqual(Season.objects.filter(gt__regex=r"^$"), []) self.assertQuerySetEqual(Season.objects.filter(gt__regex=r"^$"), [])
def test_textfield_exact_null(self):
with self.assertNumQueries(1) as ctx:
self.assertSequenceEqual(Author.objects.filter(bio=None), [self.au2])
# Columns with IS NULL condition are not wrapped (except PostgreSQL).
bio_column = connection.ops.quote_name(Author._meta.get_field("bio").column)
self.assertIn(f"{bio_column} IS NULL", ctx.captured_queries[0]["sql"])
def test_regex_non_string(self): def test_regex_non_string(self):
""" """
A regex lookup does not fail on non-string fields A regex lookup does not fail on non-string fields