[3.1.x] Refs #32096 -- Fixed __in lookup crash against key transforms for JSONField.
Regression in6789ded0a6
and1251772cb8
. Thanks Simon Charette and Igor Jerosimić for the report. Backport of7e1e198494
from master
This commit is contained in:
parent
d94e777b66
commit
59fe0b8541
|
@ -369,27 +369,26 @@ class KeyTransformIsNull(lookups.IsNull):
|
||||||
|
|
||||||
|
|
||||||
class KeyTransformIn(lookups.In):
|
class KeyTransformIn(lookups.In):
|
||||||
def process_rhs(self, compiler, connection):
|
def resolve_expression_parameter(self, compiler, connection, sql, param):
|
||||||
rhs, rhs_params = super().process_rhs(compiler, connection)
|
sql, params = super().resolve_expression_parameter(
|
||||||
if not connection.features.has_native_json_field:
|
compiler, connection, sql, param,
|
||||||
func = ()
|
)
|
||||||
|
if (
|
||||||
|
not hasattr(param, 'as_sql') and
|
||||||
|
not connection.features.has_native_json_field
|
||||||
|
):
|
||||||
if connection.vendor == 'oracle':
|
if connection.vendor == 'oracle':
|
||||||
func = []
|
value = json.loads(param)
|
||||||
for value in rhs_params:
|
if isinstance(value, (list, dict)):
|
||||||
value = json.loads(value)
|
sql = "JSON_QUERY(%s, '$.value')"
|
||||||
function = 'JSON_QUERY' if isinstance(value, (list, dict)) else 'JSON_VALUE'
|
else:
|
||||||
func.append("%s('%s', '$.value')" % (
|
sql = "JSON_VALUE(%s, '$.value')"
|
||||||
function,
|
params = (json.dumps({'value': value}),)
|
||||||
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)
|
|
||||||
elif connection.vendor in {'sqlite', 'mysql'}:
|
elif connection.vendor in {'sqlite', 'mysql'}:
|
||||||
func = ("JSON_EXTRACT(%s, '$')",) * len(rhs_params)
|
sql = "JSON_EXTRACT(%s, '$')"
|
||||||
rhs = rhs % func
|
if connection.vendor == 'mysql' and connection.mysql_is_mariadb:
|
||||||
return rhs, rhs_params
|
sql = 'JSON_UNQUOTE(%s)' % sql
|
||||||
|
return sql, params
|
||||||
|
|
||||||
|
|
||||||
class KeyTransformExact(JSONExact):
|
class KeyTransformExact(JSONExact):
|
||||||
|
|
|
@ -241,7 +241,7 @@ class FieldGetDbPrepValueIterableMixin(FieldGetDbPrepValueMixin):
|
||||||
if hasattr(param, 'resolve_expression'):
|
if hasattr(param, 'resolve_expression'):
|
||||||
param = param.resolve_expression(compiler.query)
|
param = param.resolve_expression(compiler.query)
|
||||||
if hasattr(param, 'as_sql'):
|
if hasattr(param, 'as_sql'):
|
||||||
sql, params = param.as_sql(compiler, connection)
|
sql, params = compiler.compile(param)
|
||||||
return sql, params
|
return sql, params
|
||||||
|
|
||||||
def batch_process_rhs(self, compiler, connection, rhs=None):
|
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.ArrayAgg` and
|
||||||
:class:`~django.contrib.postgres.aggregates.StringAgg` with ``ordering``
|
:class:`~django.contrib.postgres.aggregates.StringAgg` with ``ordering``
|
||||||
on key transforms for :class:`~django.db.models.JSONField` (:ticket:`32096`).
|
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], [self.objs[5]]),
|
||||||
('value__0__in', [1, 3], [self.objs[5]]),
|
('value__0__in', [1, 3], [self.objs[5]]),
|
||||||
('value__foo__in', ['bar'], [self.objs[7]]),
|
('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__foo__in', ['bar', 'baz'], [self.objs[7]]),
|
||||||
('value__bar__in', [['foo', 'bar']], [self.objs[7]]),
|
('value__bar__in', [['foo', 'bar']], [self.objs[7]]),
|
||||||
('value__bar__in', [['foo', 'bar'], ['a']], [self.objs[7]]),
|
('value__bar__in', [['foo', 'bar'], ['a']], [self.objs[7]]),
|
||||||
|
|
Loading…
Reference in New Issue