[1.11.x] Fixed #30826 -- Fixed crash of many JSONField lookups when one hand side is key transform.

Regression in 6c3dfba89215fc56fc27ef61829a6fff88be4abb.

Backport of 7d1bf29977bb368d7c28e7c6eb146db3b3009ae7 from master.
This commit is contained in:
Louise Grandjonc 2019-10-01 16:25:40 -07:00 committed by Mariusz Felisiak
parent cf2b475aab
commit a843a9ba8d
3 changed files with 33 additions and 4 deletions

View File

@ -8,7 +8,7 @@ class PostgresSimpleLookup(Lookup):
def as_sql(self, qn, connection): def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection) lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection) rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params params = tuple(lhs_params) + tuple(rhs_params)
return '%s %s %s' % (lhs, self.operator, rhs), params return '%s %s %s' % (lhs, self.operator, rhs), params

View File

@ -9,4 +9,7 @@ Django 1.11.26 fixes a regression in 1.11.25.
Bugfixes Bugfixes
======== ========
* ... * Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``,
``has_keys``, or ``has_any_keys`` lookup on
:class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand
side of an expression is a key transform (:ticket:`30826`).

View File

@ -21,7 +21,9 @@ from .models import JSONModel
try: try:
from django.contrib.postgres import forms from django.contrib.postgres import forms
from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields import JSONField
from django.contrib.postgres.fields.jsonb import KeyTransform from django.contrib.postgres.fields.jsonb import (
KeyTextTransform, KeyTransform
)
except ImportError: except ImportError:
pass pass
@ -130,7 +132,12 @@ class TestQuerying(PostgreSQLTestCase):
'k': True, 'k': True,
'l': False, 'l': False,
}), }),
JSONModel.objects.create(field={'foo': 'bar'}), JSONModel.objects.create(field={
'foo': 'bar',
'baz': {'a': 'b', 'c': 'd'},
'bar': ['foo', 'bar'],
'bax': {'foo': 'bar'},
}),
] ]
def test_exact(self): def test_exact(self):
@ -305,6 +312,25 @@ class TestQuerying(PostgreSQLTestCase):
queries[0]['sql'], queries[0]['sql'],
) )
def test_lookups_with_key_transform(self):
tests = (
('field__d__contains', 'e'),
('field__baz__contained_by', {'a': 'b', 'c': 'd', 'e': 'f'}),
('field__baz__has_key', 'c'),
('field__baz__has_keys', ['a', 'c']),
('field__baz__has_any_keys', ['a', 'x']),
('field__contains', KeyTransform('bax', 'field')),
(
'field__contained_by',
KeyTransform('x', RawSQL('%s::jsonb', ['{"x": {"a": "b", "c": 1, "d": "e"}}'])),
),
('field__has_key', KeyTextTransform('foo', 'field')),
)
for lookup, value in tests:
self.assertTrue(JSONModel.objects.filter(
**{lookup: value}
).exists())
@skipUnlessDBFeature('has_jsonb_datatype') @skipUnlessDBFeature('has_jsonb_datatype')
class TestSerialization(PostgreSQLTestCase): class TestSerialization(PostgreSQLTestCase):