From d8f093908c504ae0dbc39d3f5231f7d7920dde37 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 4 Jan 2025 20:27:28 -0500 Subject: [PATCH] Fixed #35448 -- Fixed formatting of test --debug-sql output. Also adds DatabaseOperations.format_debug_sql() hook for backends (e.g. NoSQL) to customize formatting. --- django/db/backends/base/operations.py | 4 ++++ django/db/backends/utils.py | 2 +- django/test/runner.py | 6 +----- tests/backends/tests.py | 7 ++++++- tests/test_runner/test_debug_sql.py | 26 ++++++++++++++++---------- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py index 8f2660d928..5d1f260edf 100644 --- a/django/db/backends/base/operations.py +++ b/django/db/backends/base/operations.py @@ -785,3 +785,7 @@ class BaseDatabaseOperations: rhs_expr = Col(rhs_table, rhs_field) return lhs_expr, rhs_expr + + def format_debug_sql(self, sql): + # Hook for backends (e.g. NoSQL) to customize formatting. + return sqlparse.format(sql, reindent=True, keyword_case="upper") diff --git a/django/db/backends/utils.py b/django/db/backends/utils.py index ab0ea8258b..568f510a67 100644 --- a/django/db/backends/utils.py +++ b/django/db/backends/utils.py @@ -151,7 +151,7 @@ class CursorDebugWrapper(CursorWrapper): logger.debug( "(%.3f) %s; args=%s; alias=%s", duration, - sql, + self.db.ops.format_debug_sql(sql), params, self.db.alias, extra={ diff --git a/django/test/runner.py b/django/test/runner.py index b83cd37343..097980986d 100644 --- a/django/test/runner.py +++ b/django/test/runner.py @@ -18,8 +18,6 @@ from contextlib import contextmanager from importlib import import_module from io import StringIO -import sqlparse - import django from django.core.management import call_command from django.db import connections @@ -97,9 +95,7 @@ class DebugSQLTextTestResult(unittest.TextTestResult): self.stream.writeln(self.separator2) self.stream.writeln(err) self.stream.writeln(self.separator2) - self.stream.writeln( - sqlparse.format(sql_debug, reindent=True, keyword_case="upper") - ) + self.stream.writeln(sql_debug) class PDBDebugResult(unittest.TextTestResult): diff --git a/tests/backends/tests.py b/tests/backends/tests.py index 2adfa51360..a7fd7a9bcf 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -77,7 +77,12 @@ class LastExecutedQueryTest(TestCase): connection.ops.last_executed_query(cursor, "", ()) def test_debug_sql(self): - list(Reporter.objects.filter(first_name="test")) + qs = Reporter.objects.filter(first_name="test") + ops = connections[qs.db].ops + with mock.patch.object(ops, "format_debug_sql") as format_debug_sql: + list(qs) + # Queries are formatted with DatabaseOperations.format_debug_sql(). + format_debug_sql.assert_called() sql = connection.queries[-1]["sql"].lower() self.assertIn("select", sql) self.assertIn(Reporter._meta.db_table, sql) diff --git a/tests/test_runner/test_debug_sql.py b/tests/test_runner/test_debug_sql.py index ef517fac29..e7e8d14fbd 100644 --- a/tests/test_runner/test_debug_sql.py +++ b/tests/test_runner/test_debug_sql.py @@ -91,22 +91,26 @@ class TestDebugSQL(unittest.TestCase): ( """SELECT COUNT(*) AS "__count"\n""" """FROM "test_runner_person"\n""" - """WHERE "test_runner_person"."first_name" = 'error';""" + """WHERE "test_runner_person"."first_name" = 'error'; """ + """args=('error',); alias=default""" ), ( """SELECT COUNT(*) AS "__count"\n""" """FROM "test_runner_person"\n""" - """WHERE "test_runner_person"."first_name" = 'fail';""" + """WHERE "test_runner_person"."first_name" = 'fail'; """ + """args=('fail',); alias=default""" ), ( """SELECT COUNT(*) AS "__count"\n""" """FROM "test_runner_person"\n""" - """WHERE "test_runner_person"."first_name" = 'subtest-error';""" + """WHERE "test_runner_person"."first_name" = 'subtest-error'; """ + """args=('subtest-error',); alias=default""" ), ( """SELECT COUNT(*) AS "__count"\n""" """FROM "test_runner_person"\n""" - """WHERE "test_runner_person"."first_name" = 'subtest-fail';""" + """WHERE "test_runner_person"."first_name" = 'subtest-fail'; """ + """args=('subtest-fail',); alias=default""" ), ] @@ -122,14 +126,16 @@ class TestDebugSQL(unittest.TestCase): f"runTest ({test_class_path}.FailingSubTest{method_name}) ...", f"runTest ({test_class_path}.ErrorSubTest{method_name}) ...", ( - """SELECT COUNT(*) AS "__count" """ - """FROM "test_runner_person" WHERE """ - """"test_runner_person"."first_name" = 'pass';""" + """SELECT COUNT(*) AS "__count"\n""" + """FROM "test_runner_person"\nWHERE """ + """"test_runner_person"."first_name" = 'pass'; """ + """args=('pass',); alias=default""" ), ( - """SELECT COUNT(*) AS "__count" """ - """FROM "test_runner_person" WHERE """ - """"test_runner_person"."first_name" = 'subtest-pass';""" + """SELECT COUNT(*) AS "__count"\n""" + """FROM "test_runner_person"\nWHERE """ + """"test_runner_person"."first_name" = 'subtest-pass'; """ + """args=('subtest-pass',); alias=default""" ), ]