Fixed #30672 -- Fixed crash of JSONField/HStoreField key transforms on expressions with params.

Regression in 4f5b58f5cd.

Thanks Florian Apolloner for the report and helping with tests.
This commit is contained in:
Mariusz Felisiak 2019-08-14 15:25:35 +02:00 committed by GitHub
parent 0b8d911d28
commit 1f8382d34d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 65 additions and 2 deletions

View File

@ -86,7 +86,7 @@ class KeyTransform(Transform):
def as_sql(self, compiler, connection): def as_sql(self, compiler, connection):
lhs, params = compiler.compile(self.lhs) lhs, params = compiler.compile(self.lhs)
return '(%s -> %%s)' % lhs, [self.key_name] + params return '(%s -> %%s)' % lhs, params + [self.key_name]
class KeyTransformFactory: class KeyTransformFactory:

View File

@ -112,7 +112,7 @@ class KeyTransform(Transform):
lookup = int(self.key_name) lookup = int(self.key_name)
except ValueError: except ValueError:
lookup = self.key_name lookup = self.key_name
return '(%s %s %%s)' % (lhs, self.operator), [lookup] + params return '(%s %s %%s)' % (lhs, self.operator), params + [lookup]
class KeyTextTransform(KeyTransform): class KeyTextTransform(KeyTransform):

15
docs/releases/1.11.24.txt Normal file
View File

@ -0,0 +1,15 @@
============================
Django 1.11.24 release notes
============================
*Expected September 2, 2019*
Django 1.11.24 fixes a regression in 1.11.23.
Bugfixes
========
* Fixed crash of ``KeyTransform()`` for
:class:`~django.contrib.postgres.fields.JSONField` and
:class:`~django.contrib.postgres.fields.HStoreField` when using on
expressions with params (:ticket:`30672`).

15
docs/releases/2.1.12.txt Normal file
View File

@ -0,0 +1,15 @@
===========================
Django 2.1.12 release notes
===========================
*Expected September 2, 2019*
Django 2.1.12 fixes a regression in 2.1.11.
Bugfixes
========
* Fixed crash of ``KeyTransform()`` for
:class:`~django.contrib.postgres.fields.JSONField` and
:class:`~django.contrib.postgres.fields.HStoreField` when using on
expressions with params (:ticket:`30672`).

View File

@ -12,3 +12,8 @@ Bugfixes
* Relaxed the system check added in Django 2.2 for models to reallow use of the * Relaxed the system check added in Django 2.2 for models to reallow use of the
same ``db_table`` by multiple models when database routers are installed same ``db_table`` by multiple models when database routers are installed
(:ticket:`30673`). (:ticket:`30673`).
* Fixed crash of ``KeyTransform()`` for
:class:`~django.contrib.postgres.fields.JSONField` and
:class:`~django.contrib.postgres.fields.HStoreField` when using on
expressions with params (:ticket:`30672`).

View File

@ -44,6 +44,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
2.1.12
2.1.11 2.1.11
2.1.10 2.1.10
2.1.9 2.1.9
@ -82,6 +83,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
1.11.24
1.11.23 1.11.23
1.11.22 1.11.22
1.11.21 1.11.21

View File

@ -2,6 +2,7 @@ import json
from django.core import checks, exceptions, serializers from django.core import checks, exceptions, serializers
from django.db import connection from django.db import connection
from django.db.models.expressions import RawSQL
from django.forms import Form from django.forms import Form
from django.test.utils import CaptureQueriesContext, isolate_apps from django.test.utils import CaptureQueriesContext, isolate_apps
@ -11,6 +12,7 @@ from .models import HStoreModel, PostgreSQLModel
try: try:
from django.contrib.postgres import forms from django.contrib.postgres import forms
from django.contrib.postgres.fields import HStoreField from django.contrib.postgres.fields import HStoreField
from django.contrib.postgres.fields.hstore import KeyTransform
from django.contrib.postgres.validators import KeysValidator from django.contrib.postgres.validators import KeysValidator
except ImportError: except ImportError:
pass pass
@ -127,6 +129,13 @@ class TestQuerying(PostgreSQLTestCase):
self.objs[:2] self.objs[:2]
) )
def test_key_transform_raw_expression(self):
expr = RawSQL('%s::hstore', ['x => b, y => c'])
self.assertSequenceEqual(
HStoreModel.objects.filter(field__a=KeyTransform('x', expr)),
self.objs[:2]
)
def test_keys(self): def test_keys(self):
self.assertSequenceEqual( self.assertSequenceEqual(
HStoreModel.objects.filter(field__keys=['a']), HStoreModel.objects.filter(field__keys=['a']),

View File

@ -188,6 +188,23 @@ class TestQuerying(PostgreSQLTestCase):
operator.itemgetter('key', 'count'), operator.itemgetter('key', 'count'),
) )
def test_key_transform_raw_expression(self):
expr = RawSQL('%s::jsonb', ['{"x": "bar"}'])
self.assertSequenceEqual(
JSONModel.objects.filter(field__foo=KeyTransform('x', expr)),
[self.objs[-1]],
)
def test_key_transform_expression(self):
self.assertSequenceEqual(
JSONModel.objects.filter(field__d__0__isnull=False).annotate(
key=KeyTransform('d', 'field'),
chain=KeyTransform('0', 'key'),
expr=KeyTransform('0', Cast('key', JSONField())),
).filter(chain=F('expr')),
[self.objs[8]],
)
def test_nested_key_transform_raw_expression(self): def test_nested_key_transform_raw_expression(self):
expr = RawSQL('%s::jsonb', ['{"x": {"y": "bar"}}']) expr = RawSQL('%s::jsonb', ['{"x": {"y": "bar"}}'])
self.assertSequenceEqual( self.assertSequenceEqual(