From cc3870c30f0338a09e440430d5dcc028d23f1a02 Mon Sep 17 00:00:00 2001 From: Hannes Ljungberg Date: Mon, 9 Nov 2020 17:54:20 +0100 Subject: [PATCH] [3.1.x] Fixed #32182 -- Fixed crash of JSONField nested key transforms with subquery annotations on PostgreSQL. Backport of 0773837e15bb632afffb6848a58c59a791008fa1 from master --- django/db/models/fields/json.py | 3 ++- docs/releases/3.1.4.txt | 3 +++ tests/model_fields/test_jsonfield.py | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py index 5b0272a945..94596556d2 100644 --- a/django/db/models/fields/json.py +++ b/django/db/models/fields/json.py @@ -302,7 +302,8 @@ class KeyTransform(Transform): def as_postgresql(self, compiler, connection): lhs, params, key_transforms = self.preprocess_lhs(compiler, connection) if len(key_transforms) > 1: - return '(%s %s %%s)' % (lhs, self.postgres_nested_operator), params + [key_transforms] + sql = '(%s %s %%s)' % (lhs, self.postgres_nested_operator) + return sql, tuple(params) + (key_transforms,) try: lookup = int(self.key_name) except ValueError: diff --git a/docs/releases/3.1.4.txt b/docs/releases/3.1.4.txt index 6641b0aaf5..02408cca68 100644 --- a/docs/releases/3.1.4.txt +++ b/docs/releases/3.1.4.txt @@ -14,3 +14,6 @@ Bugfixes * Fixed passing extra HTTP headers to ``AsyncRequestFactory`` request methods (:ticket:`32159`). + +* Fixed crash of key transforms for :class:`~django.db.models.JSONField` on + PostgreSQL when using on a ``Subquery()`` annotation (:ticket:`32182`). diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index ea9bc2775b..b91d94752f 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -385,6 +385,18 @@ class TestQuerying(TestCase): [self.objs[4]], ) + def test_nested_key_transform_on_subquery(self): + self.assertSequenceEqual( + NullableJSONModel.objects.filter(value__d__0__isnull=False).annotate( + subquery_value=Subquery( + NullableJSONModel.objects.filter(pk=OuterRef('pk')).values('value') + ), + key=KeyTransform('d', 'subquery_value'), + chain=KeyTransform('f', KeyTransform('1', 'key')), + ).filter(chain='g'), + [self.objs[4]], + ) + def test_expression_wrapper_key_transform(self): self.assertSequenceEqual( NullableJSONModel.objects.annotate(