diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py index 809466fc7f..ef697e85b0 100644 --- a/django/db/backends/postgresql/features.py +++ b/django/db/backends/postgresql/features.py @@ -105,6 +105,15 @@ class DatabaseFeatures(BaseDatabaseFeatures): }, } ) + if self.uses_server_side_binding: + skips.update( + { + "The actual query cannot be determined for server side bindings": { + "backends.base.test_base.ExecuteWrapperTests." + "test_wrapper_debug", + } + }, + ) return skips @cached_property diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py index 06981bc094..4e444d5f2b 100644 --- a/django/db/backends/postgresql/operations.py +++ b/django/db/backends/postgresql/operations.py @@ -296,9 +296,14 @@ class DatabaseOperations(BaseDatabaseOperations): if is_psycopg3: def last_executed_query(self, cursor, sql, params): - try: - return self.compose_sql(sql, params) - except errors.DataError: + if self.connection.features.uses_server_side_binding: + try: + return self.compose_sql(sql, params) + except errors.DataError: + return None + else: + if cursor._query and cursor._query.query is not None: + return cursor._query.query.decode() return None else: diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index 713d8bd38f..d95c6fb2d1 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -89,6 +89,9 @@ class DatabaseFeatures(BaseDatabaseFeatures): "db_functions.math.test_round.RoundTests." "test_integer_with_negative_precision", }, + "The actual query cannot be determined on SQLite": { + "backends.base.test_base.ExecuteWrapperTests.test_wrapper_debug", + }, } if self.connection.is_in_memory_db(): skips.update( diff --git a/tests/backends/base/test_base.py b/tests/backends/base/test_base.py index 03356fbf10..4418d010ea 100644 --- a/tests/backends/base/test_base.py +++ b/tests/backends/base/test_base.py @@ -211,6 +211,16 @@ class ExecuteWrapperTests(TestCase): self.assertEqual(connection.execute_wrappers, []) self.assertEqual(connections["other"].execute_wrappers, []) + def test_wrapper_debug(self): + def wrap_with_comment(execute, sql, params, many, context): + return execute(f"/* My comment */ {sql}", params, many, context) + + with CaptureQueriesContext(connection) as ctx: + with connection.execute_wrapper(wrap_with_comment): + list(Person.objects.all()) + last_query = ctx.captured_queries[-1]["sql"] + self.assertTrue(last_query.startswith("/* My comment */")) + class ConnectionHealthChecksTests(SimpleTestCase): databases = {"default"}