mirror of
https://github.com/django/django.git
synced 2025-07-17 16:19:12 +00:00
[3.1.x] Refs #32096 -- Fixed __in lookup crash against key transforms for JSONField.
Regression in 6789ded0a6ab797f0dcdfa6ad5d1cfa46e23abcd and 1251772cb83aa4106f526fe00738e51c0eb59122. Thanks Simon Charette and Igor Jerosimić for the report. Backport of 7e1e198494d4fc72cf6e153f9d24fe2493c17dc1 from master
This commit is contained in:
parent
d94e777b66
commit
59fe0b8541
@ -369,27 +369,26 @@ class KeyTransformIsNull(lookups.IsNull):
|
||||
|
||||
|
||||
class KeyTransformIn(lookups.In):
|
||||
def process_rhs(self, compiler, connection):
|
||||
rhs, rhs_params = super().process_rhs(compiler, connection)
|
||||
if not connection.features.has_native_json_field:
|
||||
func = ()
|
||||
def resolve_expression_parameter(self, compiler, connection, sql, param):
|
||||
sql, params = super().resolve_expression_parameter(
|
||||
compiler, connection, sql, param,
|
||||
)
|
||||
if (
|
||||
not hasattr(param, 'as_sql') and
|
||||
not connection.features.has_native_json_field
|
||||
):
|
||||
if connection.vendor == 'oracle':
|
||||
func = []
|
||||
for value in rhs_params:
|
||||
value = json.loads(value)
|
||||
function = 'JSON_QUERY' if isinstance(value, (list, dict)) else 'JSON_VALUE'
|
||||
func.append("%s('%s', '$.value')" % (
|
||||
function,
|
||||
json.dumps({'value': value}),
|
||||
))
|
||||
func = tuple(func)
|
||||
rhs_params = ()
|
||||
elif connection.vendor == 'mysql' and connection.mysql_is_mariadb:
|
||||
func = ("JSON_UNQUOTE(JSON_EXTRACT(%s, '$'))",) * len(rhs_params)
|
||||
value = json.loads(param)
|
||||
if isinstance(value, (list, dict)):
|
||||
sql = "JSON_QUERY(%s, '$.value')"
|
||||
else:
|
||||
sql = "JSON_VALUE(%s, '$.value')"
|
||||
params = (json.dumps({'value': value}),)
|
||||
elif connection.vendor in {'sqlite', 'mysql'}:
|
||||
func = ("JSON_EXTRACT(%s, '$')",) * len(rhs_params)
|
||||
rhs = rhs % func
|
||||
return rhs, rhs_params
|
||||
sql = "JSON_EXTRACT(%s, '$')"
|
||||
if connection.vendor == 'mysql' and connection.mysql_is_mariadb:
|
||||
sql = 'JSON_UNQUOTE(%s)' % sql
|
||||
return sql, params
|
||||
|
||||
|
||||
class KeyTransformExact(JSONExact):
|
||||
|
@ -241,7 +241,7 @@ class FieldGetDbPrepValueIterableMixin(FieldGetDbPrepValueMixin):
|
||||
if hasattr(param, 'resolve_expression'):
|
||||
param = param.resolve_expression(compiler.query)
|
||||
if hasattr(param, 'as_sql'):
|
||||
sql, params = param.as_sql(compiler, connection)
|
||||
sql, params = compiler.compile(param)
|
||||
return sql, params
|
||||
|
||||
def batch_process_rhs(self, compiler, connection, rhs=None):
|
||||
|
@ -25,3 +25,7 @@ Bugfixes
|
||||
:class:`~django.contrib.postgres.aggregates.ArrayAgg` and
|
||||
:class:`~django.contrib.postgres.aggregates.StringAgg` with ``ordering``
|
||||
on key transforms for :class:`~django.db.models.JSONField` (:ticket:`32096`).
|
||||
|
||||
* Fixed a regression in Django 3.1 that caused a crash of ``__in`` lookup when
|
||||
using key transforms for :class:`~django.db.models.JSONField` in the lookup
|
||||
value (:ticket:`32096`).
|
||||
|
@ -631,6 +631,16 @@ class TestQuerying(TestCase):
|
||||
('value__0__in', [1], [self.objs[5]]),
|
||||
('value__0__in', [1, 3], [self.objs[5]]),
|
||||
('value__foo__in', ['bar'], [self.objs[7]]),
|
||||
(
|
||||
'value__foo__in',
|
||||
[KeyTransform('foo', KeyTransform('bax', 'value'))],
|
||||
[self.objs[7]],
|
||||
),
|
||||
(
|
||||
'value__foo__in',
|
||||
[KeyTransform('foo', KeyTransform('bax', 'value')), 'baz'],
|
||||
[self.objs[7]],
|
||||
),
|
||||
('value__foo__in', ['bar', 'baz'], [self.objs[7]]),
|
||||
('value__bar__in', [['foo', 'bar']], [self.objs[7]]),
|
||||
('value__bar__in', [['foo', 'bar'], ['a']], [self.objs[7]]),
|
||||
|
Loading…
x
Reference in New Issue
Block a user