Fixed #34080 -- Fixed __exact lookup when nested arrays contain only NULL values.

Thanks jerch and David Sanders for reviews.
This commit is contained in:
Ion Alberdi 2022-10-09 11:01:14 +02:00 committed by Mariusz Felisiak
parent 34d63d5a41
commit 3dc9f3ac69
2 changed files with 28 additions and 1 deletions

View File

@ -237,7 +237,9 @@ class ArrayField(CheckFieldDefaultMixin, Field):
class ArrayRHSMixin: class ArrayRHSMixin:
def __init__(self, lhs, rhs): def __init__(self, lhs, rhs):
if isinstance(rhs, (tuple, list)): # Don't wrap arrays that contains only None values, psycopg2 doesn't
# allow this.
if isinstance(rhs, (tuple, list)) and any(self._rhs_not_none_values(rhs)):
expressions = [] expressions = []
for value in rhs: for value in rhs:
if not hasattr(value, "resolve_expression"): if not hasattr(value, "resolve_expression"):
@ -256,6 +258,13 @@ class ArrayRHSMixin:
cast_type = self.lhs.output_field.cast_db_type(connection) cast_type = self.lhs.output_field.cast_db_type(connection)
return "%s::%s" % (rhs, cast_type), rhs_params return "%s::%s" % (rhs, cast_type), rhs_params
def _rhs_not_none_values(self, rhs):
for x in rhs:
if isinstance(x, (list, tuple)):
yield from self._rhs_not_none_values(x)
elif x is not None:
yield True
@ArrayField.register_lookup @ArrayField.register_lookup
class ArrayContains(ArrayRHSMixin, lookups.DataContains): class ArrayContains(ArrayRHSMixin, lookups.DataContains):

View File

@ -253,6 +253,24 @@ class TestQuerying(PostgreSQLTestCase):
[obj], [obj],
) )
def test_exact_null_only_nested_array(self):
obj1 = NullableIntegerArrayModel.objects.create(field_nested=[[None, None]])
obj2 = NullableIntegerArrayModel.objects.create(
field_nested=[[None, None], [None, None]],
)
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(
field_nested__exact=[[None, None]],
),
[obj1],
)
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(
field_nested__exact=[[None, None], [None, None]],
),
[obj2],
)
def test_exact_with_expression(self): def test_exact_with_expression(self):
self.assertSequenceEqual( self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(field__exact=[Value(1)]), NullableIntegerArrayModel.objects.filter(field__exact=[Value(1)]),