1
0
mirror of https://github.com/django/django.git synced 2025-01-26 18:19:18 +00:00

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

Regression in 09ffc5c1212d4ced58b708cbbf3dfbfb77b782ca.

Thanks Michael Smith for the report.

This also reverts commit 1e4da439556cdd69eb9f91e07f99cf77997e70d2.
Backport of 1586a09b7949bbb7b0d84cb74ce1cadc25cbb355 from main
This commit is contained in:
Mariusz Felisiak 2023-05-08 19:34:30 +02:00
parent dc3b8190ed
commit e0d8981139
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(
@ -1000,6 +1000,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