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:
parent
dc3b8190ed
commit
e0d8981139
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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`).
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user