Repository: django/django
File: django/db/models/fields/json.py (Python)

Code before:
            rhs_params = ("null",)
        if connection.vendor == "mysql" and not isinstance(self.rhs, JSONNull):
            func = ["JSON_EXTRACT(%s, '$')"] * len(rhs_params)
            rhs %= tuple(func)
        return rhs, rhs_params

    def as_oracle(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        if connection.features.supports_primitives_in_json_field:
            lhs = f"JSON({lhs})"
            rhs = f"JSON({rhs})"
        return f"JSON_EQUAL({lhs}, {rhs} ERROR ON ERROR)", (*lhs_params, *rhs_params)


class JSONIContains(CaseInsensitiveMixin, lookups.IContains):
    pass


class ProcessJSONLHSMixin:
    def _get_json_path(self, connection, key_transforms):
        if key_transforms is None:
            json_path = "$"
        else:
            json_path = connection.ops.compile_json_path(key_transforms)
        return json_path

    def _process_as_oracle(self, sql, params, connection, key_transforms=None):
        json_path = self._get_json_path(connection, key_transforms)
        if connection.features.supports_primitives_in_json_field:
            template = (
                "COALESCE("
                "JSON_VALUE(%s, q'\uffff%s\uffff'),"
                "JSON_QUERY(%s, q'\uffff%s\uffff' DISALLOW SCALARS)"
                ")"
            )
        else:
            template = (
                "COALESCE("
                "JSON_QUERY(%s, q'\uffff%s\uffff'),"
                "JSON_VALUE(%s, q'\uffff%s\uffff')"
                ")"
            )
        # Add paths directly into SQL because path expressions cannot be passed
        # as bind variables on Oracle. Use a custom delimiter to prevent the
        # JSON path from escaping the SQL literal. Each key in the JSON path is
        # passed through json.dumps() with ensure_ascii=True (the default),
        # which converts the delimiter into the escaped \uffff format. This
        # ensures that the delimiter is not present in the JSON path.
        sql = template % ((sql, json_path) * 2)
        return sql, params * 2

Review comment (suggestion):
```suggestion
        if key_transforms is None:
            return "$"
        return connection.ops.compile_json_path(key_transforms)
```

Code after:
        # Treat None lookup values as null.
        if rhs == "%s" and (*rhs_params,) == (None,):
            rhs_params = ("null",)
        if connection.vendor == "mysql" and not isinstance(self.rhs, JSONNull):
            func = ["JSON_EXTRACT(%s, '$')"] * len(rhs_params)
            rhs %= tuple(func)
        return rhs, rhs_params

    def as_oracle(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        if connection.features.supports_primitives_in_json_field:
            lhs = f"JSON({lhs})"
            rhs = f"JSON({rhs})"
        return f"JSON_EQUAL({lhs}, {rhs} ERROR ON ERROR)", (*lhs_params, *rhs_params)


class JSONIContains(CaseInsensitiveMixin, lookups.IContains):
    pass


class ProcessJSONLHSMixin:
    def _get_json_path(self, connection, key_transforms):
        if key_transforms is None:
            return "$"
        return connection.ops.compile_json_path(key_transforms)

    def _process_as_oracle(self, sql, params, connection, key_transforms=None):
        json_path = self._get_json_path(connection, key_transforms)
        if connection.features.supports_primitives_in_json_field:
            template = (
                "COALESCE("
                "JSON_VALUE(%s, q'\uffff%s\uffff'),"
                "JSON_QUERY(%s, q'\uffff%s\uffff' DISALLOW SCALARS)"
                ")"
            )
        else:
            template = (
                "COALESCE("
                "JSON_QUERY(%s, q'\uffff%s\uffff'),"
                "JSON_VALUE(%s, q'\uffff%s\uffff')"
                ")"
            )
        # Add paths directly into SQL because path expressions cannot be passed
        # as bind variables on Oracle. Use a custom delimiter to prevent the
        # JSON path from escaping the SQL literal. Each key in the JSON path is
        # passed through json.dumps() with ensure_ascii=True (the default),
        # which converts the delimiter into the escaped \uffff format. This
        # ensures that the delimiter is not present in the JSON path.
        sql = template % ((sql, json_path) * 2)
        return sql, params * 2