summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhesham942 <heshamhatem2004@gmail.com>2025-05-13 13:37:02 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-05-14 13:21:18 +0200
commita8716f3c4c6d78d38ce86d79c816062346dcc5bf (patch)
tree482900744d3eb4fda1772396deb753319d272dc3
parent6e36f7f78415e454dcde1d9ee33f2d2c7fdfdfad (diff)
Refs #36085 -- Moved compile_json_path to BaseDatabaseOperations.
-rw-r--r--django/db/backends/base/operations.py15
-rw-r--r--django/db/models/fields/json.py35
2 files changed, 27 insertions, 23 deletions
diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py
index fea73bc1e4..ba6650ed69 100644
--- a/django/db/backends/base/operations.py
+++ b/django/db/backends/base/operations.py
@@ -792,3 +792,18 @@ class BaseDatabaseOperations:
def format_debug_sql(self, sql):
# Hook for backends (e.g. NoSQL) to customize formatting.
return sqlparse.format(sql, reindent=True, keyword_case="upper")
+
+ def compile_json_path(self, key_transforms, include_root=True):
+ """
+ Hook for backends to customize all aspects of JSON path construction.
+ """
+ path = ["$"] if include_root else []
+ for key_transform in key_transforms:
+ try:
+ num = int(key_transform)
+ except ValueError: # Non-integer.
+ path.append(".")
+ path.append(json.dumps(key_transform))
+ else:
+ path.append("[%s]" % num)
+ return "".join(path)
diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py
index 2fc1abb032..d544caf3e5 100644
--- a/django/db/models/fields/json.py
+++ b/django/db/models/fields/json.py
@@ -148,19 +148,6 @@ class JSONField(CheckFieldDefaultMixin, Field):
)
-def compile_json_path(key_transforms, include_root=True):
- path = ["$"] if include_root else []
- for key_transform in key_transforms:
- try:
- num = int(key_transform)
- except ValueError: # non-integer
- path.append(".")
- path.append(json.dumps(key_transform))
- else:
- path.append("[%s]" % num)
- return "".join(path)
-
-
class DataContains(FieldGetDbPrepValueMixin, PostgresOperatorLookup):
lookup_name = "contains"
postgres_operator = "@>"
@@ -194,7 +181,7 @@ class ContainedBy(FieldGetDbPrepValueMixin, PostgresOperatorLookup):
class HasKeyLookup(PostgresOperatorLookup):
logical_operator = None
- def compile_json_path_final_key(self, key_transform):
+ def compile_json_path_final_key(self, connection, key_transform):
# Compile the final key without interpreting ints as array elements.
return ".%s" % json.dumps(key_transform)
@@ -204,7 +191,7 @@ class HasKeyLookup(PostgresOperatorLookup):
lhs_sql, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs(
compiler, connection
)
- lhs_json_path = compile_json_path(lhs_key_transforms)
+ lhs_json_path = connection.ops.compile_json_path(lhs_key_transforms)
else:
lhs_sql, lhs_params = self.process_lhs(compiler, connection)
lhs_json_path = "$"
@@ -218,8 +205,10 @@ class HasKeyLookup(PostgresOperatorLookup):
else:
rhs_key_transforms = [key]
*rhs_key_transforms, final_key = rhs_key_transforms
- rhs_json_path = compile_json_path(rhs_key_transforms, include_root=False)
- rhs_json_path += self.compile_json_path_final_key(final_key)
+ rhs_json_path = connection.ops.compile_json_path(
+ rhs_key_transforms, include_root=False
+ )
+ rhs_json_path += self.compile_json_path_final_key(connection, final_key)
yield lhs_sql, lhs_params, lhs_json_path + rhs_json_path
def _combine_sql_parts(self, parts):
@@ -296,8 +285,8 @@ class HasAnyKeys(HasKeys):
class HasKeyOrArrayIndex(HasKey):
- def compile_json_path_final_key(self, key_transform):
- return compile_json_path([key_transform], include_root=False)
+ def compile_json_path_final_key(self, connection, key_transform):
+ return connection.ops.compile_json_path([key_transform], include_root=False)
class CaseInsensitiveMixin:
@@ -378,12 +367,12 @@ class KeyTransform(Transform):
def as_mysql(self, compiler, connection):
lhs, params, key_transforms = self.preprocess_lhs(compiler, connection)
- json_path = compile_json_path(key_transforms)
+ json_path = connection.ops.compile_json_path(key_transforms)
return "JSON_EXTRACT(%s, %%s)" % lhs, (*params, json_path)
def as_oracle(self, compiler, connection):
lhs, params, key_transforms = self.preprocess_lhs(compiler, connection)
- json_path = compile_json_path(key_transforms)
+ json_path = connection.ops.compile_json_path(key_transforms)
if connection.features.supports_primitives_in_json_field:
sql = (
"COALESCE("
@@ -419,7 +408,7 @@ class KeyTransform(Transform):
def as_sqlite(self, compiler, connection):
lhs, params, key_transforms = self.preprocess_lhs(compiler, connection)
- json_path = compile_json_path(key_transforms)
+ json_path = connection.ops.compile_json_path(key_transforms)
datatype_values = ",".join(
[repr(datatype) for datatype in connection.ops.jsonfield_datatype_values]
)
@@ -441,7 +430,7 @@ class KeyTextTransform(KeyTransform):
return "JSON_UNQUOTE(%s)" % sql, params
else:
lhs, params, key_transforms = self.preprocess_lhs(compiler, connection)
- json_path = compile_json_path(key_transforms)
+ json_path = connection.ops.compile_json_path(key_transforms)
return "(%s ->> %%s)" % lhs, (*params, json_path)
@classmethod