1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

Refs #36085 -- Moved compile_json_path to BaseDatabaseOperations.

This commit is contained in:
hesham942 2025-05-13 13:37:02 +02:00 committed by Sarah Boyce
parent 6e36f7f784
commit a8716f3c4c
2 changed files with 27 additions and 23 deletions

View File

@ -792,3 +792,18 @@ class BaseDatabaseOperations:
def format_debug_sql(self, sql): def format_debug_sql(self, sql):
# Hook for backends (e.g. NoSQL) to customize formatting. # Hook for backends (e.g. NoSQL) to customize formatting.
return sqlparse.format(sql, reindent=True, keyword_case="upper") 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)

View File

@ -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): class DataContains(FieldGetDbPrepValueMixin, PostgresOperatorLookup):
lookup_name = "contains" lookup_name = "contains"
postgres_operator = "@>" postgres_operator = "@>"
@ -194,7 +181,7 @@ class ContainedBy(FieldGetDbPrepValueMixin, PostgresOperatorLookup):
class HasKeyLookup(PostgresOperatorLookup): class HasKeyLookup(PostgresOperatorLookup):
logical_operator = None 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. # Compile the final key without interpreting ints as array elements.
return ".%s" % json.dumps(key_transform) return ".%s" % json.dumps(key_transform)
@ -204,7 +191,7 @@ class HasKeyLookup(PostgresOperatorLookup):
lhs_sql, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs( lhs_sql, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs(
compiler, connection compiler, connection
) )
lhs_json_path = compile_json_path(lhs_key_transforms) lhs_json_path = connection.ops.compile_json_path(lhs_key_transforms)
else: else:
lhs_sql, lhs_params = self.process_lhs(compiler, connection) lhs_sql, lhs_params = self.process_lhs(compiler, connection)
lhs_json_path = "$" lhs_json_path = "$"
@ -218,8 +205,10 @@ class HasKeyLookup(PostgresOperatorLookup):
else: else:
rhs_key_transforms = [key] rhs_key_transforms = [key]
*rhs_key_transforms, final_key = rhs_key_transforms *rhs_key_transforms, final_key = rhs_key_transforms
rhs_json_path = compile_json_path(rhs_key_transforms, include_root=False) rhs_json_path = connection.ops.compile_json_path(
rhs_json_path += self.compile_json_path_final_key(final_key) 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 yield lhs_sql, lhs_params, lhs_json_path + rhs_json_path
def _combine_sql_parts(self, parts): def _combine_sql_parts(self, parts):
@ -296,8 +285,8 @@ class HasAnyKeys(HasKeys):
class HasKeyOrArrayIndex(HasKey): class HasKeyOrArrayIndex(HasKey):
def compile_json_path_final_key(self, key_transform): def compile_json_path_final_key(self, connection, key_transform):
return compile_json_path([key_transform], include_root=False) return connection.ops.compile_json_path([key_transform], include_root=False)
class CaseInsensitiveMixin: class CaseInsensitiveMixin:
@ -378,12 +367,12 @@ class KeyTransform(Transform):
def as_mysql(self, compiler, connection): def as_mysql(self, compiler, connection):
lhs, params, key_transforms = self.preprocess_lhs(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) return "JSON_EXTRACT(%s, %%s)" % lhs, (*params, json_path)
def as_oracle(self, compiler, connection): def as_oracle(self, compiler, connection):
lhs, params, key_transforms = self.preprocess_lhs(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: if connection.features.supports_primitives_in_json_field:
sql = ( sql = (
"COALESCE(" "COALESCE("
@ -419,7 +408,7 @@ class KeyTransform(Transform):
def as_sqlite(self, compiler, connection): def as_sqlite(self, compiler, connection):
lhs, params, key_transforms = self.preprocess_lhs(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( datatype_values = ",".join(
[repr(datatype) for datatype in connection.ops.jsonfield_datatype_values] [repr(datatype) for datatype in connection.ops.jsonfield_datatype_values]
) )
@ -441,7 +430,7 @@ class KeyTextTransform(KeyTransform):
return "JSON_UNQUOTE(%s)" % sql, params return "JSON_UNQUOTE(%s)" % sql, params
else: else:
lhs, params, key_transforms = self.preprocess_lhs(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 "(%s ->> %%s)" % lhs, (*params, json_path) return "(%s ->> %%s)" % lhs, (*params, json_path)
@classmethod @classmethod