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])
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):
return None
@ -344,7 +338,9 @@ END;
def lookup_cast(self, lookup_type, internal_type=None):
if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"):
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 "%s"

View File

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

View File

@ -9,4 +9,6 @@ Django 4.2.2 fixes several bugs in 4.2.1.
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):
name = models.CharField(max_length=100)
alias = models.CharField(max_length=50, null=True, blank=True)
bio = models.TextField(null=True)
class Meta:
ordering = ("name",)
@ -50,22 +51,11 @@ class NulledTextField(models.TextField):
return None if value == "" else value
class NullField(models.Field):
pass
NullField.register_lookup(IsNull)
@NulledTextField.register_lookup
class NulledTransform(models.Transform):
lookup_name = "nulled"
template = "NULL"
@property
def output_field(self):
return NullField()
@NulledTextField.register_lookup
class IsNullWithNoneAsRHS(IsNull):

View File

@ -49,7 +49,7 @@ class LookupTests(TestCase):
@classmethod
def setUpTestData(cls):
# 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")
# Create a few Articles.
cls.a1 = Article.objects.create(
@ -1029,6 +1029,13 @@ class LookupTests(TestCase):
Season.objects.create(year=2012, gt=None)
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):
"""
A regex lookup does not fail on non-string fields