Fixed #32411 -- Fixed __icontains lookup for JSONField on MySQL.
This commit is contained in:
parent
51637222b6
commit
63d239db03
|
@ -237,6 +237,26 @@ class HasAnyKeys(HasKeys):
|
||||||
logical_operator = ' OR '
|
logical_operator = ' OR '
|
||||||
|
|
||||||
|
|
||||||
|
class CaseInsensitiveMixin:
|
||||||
|
"""
|
||||||
|
Mixin to allow case-insensitive comparison of JSON values on MySQL.
|
||||||
|
MySQL handles strings used in JSON context using the utf8mb4_bin collation.
|
||||||
|
Because utf8mb4_bin is a binary collation, comparison of JSON values is
|
||||||
|
case-sensitive.
|
||||||
|
"""
|
||||||
|
def process_lhs(self, compiler, connection):
|
||||||
|
lhs, lhs_params = super().process_lhs(compiler, connection)
|
||||||
|
if connection.vendor == 'mysql':
|
||||||
|
return 'LOWER(%s)' % lhs, lhs_params
|
||||||
|
return lhs, lhs_params
|
||||||
|
|
||||||
|
def process_rhs(self, compiler, connection):
|
||||||
|
rhs, rhs_params = super().process_rhs(compiler, connection)
|
||||||
|
if connection.vendor == 'mysql':
|
||||||
|
return 'LOWER(%s)' % rhs, rhs_params
|
||||||
|
return rhs, rhs_params
|
||||||
|
|
||||||
|
|
||||||
class JSONExact(lookups.Exact):
|
class JSONExact(lookups.Exact):
|
||||||
can_use_none_as_rhs = True
|
can_use_none_as_rhs = True
|
||||||
|
|
||||||
|
@ -260,12 +280,17 @@ class JSONExact(lookups.Exact):
|
||||||
return rhs, rhs_params
|
return rhs, rhs_params
|
||||||
|
|
||||||
|
|
||||||
|
class JSONIContains(CaseInsensitiveMixin, lookups.IContains):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
JSONField.register_lookup(DataContains)
|
JSONField.register_lookup(DataContains)
|
||||||
JSONField.register_lookup(ContainedBy)
|
JSONField.register_lookup(ContainedBy)
|
||||||
JSONField.register_lookup(HasKey)
|
JSONField.register_lookup(HasKey)
|
||||||
JSONField.register_lookup(HasKeys)
|
JSONField.register_lookup(HasKeys)
|
||||||
JSONField.register_lookup(HasAnyKeys)
|
JSONField.register_lookup(HasAnyKeys)
|
||||||
JSONField.register_lookup(JSONExact)
|
JSONField.register_lookup(JSONExact)
|
||||||
|
JSONField.register_lookup(JSONIContains)
|
||||||
|
|
||||||
|
|
||||||
class KeyTransform(Transform):
|
class KeyTransform(Transform):
|
||||||
|
@ -343,26 +368,6 @@ class KeyTransformTextLookupMixin:
|
||||||
super().__init__(key_text_transform, *args, **kwargs)
|
super().__init__(key_text_transform, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CaseInsensitiveMixin:
|
|
||||||
"""
|
|
||||||
Mixin to allow case-insensitive comparison of JSON values on MySQL.
|
|
||||||
MySQL handles strings used in JSON context using the utf8mb4_bin collation.
|
|
||||||
Because utf8mb4_bin is a binary collation, comparison of JSON values is
|
|
||||||
case-sensitive.
|
|
||||||
"""
|
|
||||||
def process_lhs(self, compiler, connection):
|
|
||||||
lhs, lhs_params = super().process_lhs(compiler, connection)
|
|
||||||
if connection.vendor == 'mysql':
|
|
||||||
return 'LOWER(%s)' % lhs, lhs_params
|
|
||||||
return lhs, lhs_params
|
|
||||||
|
|
||||||
def process_rhs(self, compiler, connection):
|
|
||||||
rhs, rhs_params = super().process_rhs(compiler, connection)
|
|
||||||
if connection.vendor == 'mysql':
|
|
||||||
return 'LOWER(%s)' % rhs, rhs_params
|
|
||||||
return rhs, rhs_params
|
|
||||||
|
|
||||||
|
|
||||||
class KeyTransformIsNull(lookups.IsNull):
|
class KeyTransformIsNull(lookups.IsNull):
|
||||||
# key__isnull=False is the same as has_key='key'
|
# key__isnull=False is the same as has_key='key'
|
||||||
def as_oracle(self, compiler, connection):
|
def as_oracle(self, compiler, connection):
|
||||||
|
|
|
@ -313,6 +313,12 @@ class TestQuerying(TestCase):
|
||||||
[self.objs[3]],
|
[self.objs[3]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_icontains(self):
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
NullableJSONModel.objects.filter(value__icontains='BaX'),
|
||||||
|
self.objs[6:8],
|
||||||
|
)
|
||||||
|
|
||||||
def test_isnull(self):
|
def test_isnull(self):
|
||||||
self.assertSequenceEqual(
|
self.assertSequenceEqual(
|
||||||
NullableJSONModel.objects.filter(value__isnull=True),
|
NullableJSONModel.objects.filter(value__isnull=True),
|
||||||
|
|
Loading…
Reference in New Issue