summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2022-08-18 21:02:29 +0200
committerGitHub <noreply@github.com>2022-08-18 21:02:29 +0200
commite9fd2b572410b1236da0d3d0933014138d89f44e (patch)
tree80eed25210c6bdddbc0ded52364172cf752c830a
parentbd3602310073edde7220a61ca85dbf128e8ee6ac (diff)
Refs #26511 -- Fixed json.KeyTextTransform() on MySQL/MariaDB.
-rw-r--r--django/db/models/fields/json.py12
-rw-r--r--tests/model_fields/test_jsonfield.py14
2 files changed, 25 insertions, 1 deletions
diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py
index 7424f46e66..16231f24ac 100644
--- a/django/db/models/fields/json.py
+++ b/django/db/models/fields/json.py
@@ -4,6 +4,7 @@ from django import forms
from django.core import checks, exceptions
from django.db import NotSupportedError, connections, router
from django.db.models import lookups
+from django.db.models.fields import TextField
from django.db.models.lookups import PostgresOperatorLookup, Transform
from django.utils.translation import gettext_lazy as _
@@ -366,6 +367,17 @@ class KeyTransform(Transform):
class KeyTextTransform(KeyTransform):
postgres_operator = "->>"
postgres_nested_operator = "#>>"
+ output_field = TextField()
+
+ def as_mysql(self, compiler, connection):
+ if connection.mysql_is_mariadb:
+ # MariaDB doesn't support -> and ->> operators (see MDEV-13594).
+ sql, params = super().as_mysql(compiler, connection)
+ return "JSON_UNQUOTE(%s)" % sql, params
+ else:
+ lhs, params, key_transforms = self.preprocess_lhs(compiler, connection)
+ json_path = compile_json_path(key_transforms)
+ return "(%s ->> %%s)" % lhs, tuple(params) + (json_path,)
class KeyTransformTextLookupMixin:
diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py
index 25dfef7a24..d6b9f031b1 100644
--- a/tests/model_fields/test_jsonfield.py
+++ b/tests/model_fields/test_jsonfield.py
@@ -370,6 +370,7 @@ class TestQuerying(TestCase):
).order_by("key"),
):
self.assertSequenceEqual(qs, [self.objs[4]])
+ none_val = "" if connection.features.interprets_empty_strings_as_nulls else None
qs = NullableJSONModel.objects.filter(value__isnull=False)
self.assertQuerysetEqual(
qs.filter(value__isnull=False)
@@ -381,7 +382,7 @@ class TestQuerying(TestCase):
.values("key")
.annotate(count=Count("key"))
.order_by("count"),
- [(None, 0), ("g", 1)],
+ [(none_val, 0), ("g", 1)],
operator.itemgetter("key", "count"),
)
@@ -494,6 +495,17 @@ class TestQuerying(TestCase):
[self.objs[4]],
)
+ def test_key_text_transform_char_lookup(self):
+ qs = NullableJSONModel.objects.annotate(
+ char_value=KeyTextTransform("foo", "value"),
+ ).filter(char_value__startswith="bar")
+ self.assertSequenceEqual(qs, [self.objs[7]])
+
+ qs = NullableJSONModel.objects.annotate(
+ char_value=KeyTextTransform(1, KeyTextTransform("bar", "value")),
+ ).filter(char_value__startswith="bar")
+ self.assertSequenceEqual(qs, [self.objs[7]])
+
def test_expression_wrapper_key_transform(self):
self.assertCountEqual(
NullableJSONModel.objects.annotate(