Skip to content

Commit 7da3aa9

Browse files
committed
Simplify implementation per review feedback
- Move length check into parse_sql instead of adding utility function - Rename setting to PRETTIFY_SQL_MAX_LENGTH to match PRETTIFY_SQL - Change default to 10000 to match sqlparse's MAX_GROUPING_TOKENS - Remove _format_skipped_sql function (just return escaped SQL) - Move test imports to file top
1 parent 0809510 commit 7da3aa9

File tree

4 files changed

+24
-62
lines changed

4 files changed

+24
-62
lines changed

debug_toolbar/panels/sql/utils.py

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -91,54 +91,21 @@ def is_select_query(sql):
9191
return sql.lower().lstrip(" (").startswith("select")
9292

9393

94-
def _format_skipped_sql(sql, reason):
95-
"""
96-
Format SQL that was skipped from prettification.
97-
98-
Shows a notice and the first portion of raw SQL for debugging.
99-
"""
100-
preview_length = 500
101-
preview = escape(sql[:preview_length])
102-
total_length = len(sql)
103-
104-
if total_length > preview_length:
105-
suffix = f"\n\n... ({total_length - preview_length:,} more characters)"
106-
else:
107-
suffix = ""
108-
109-
return (
110-
f'<span class="djdt-sql-skipped">'
111-
f"<em>SQL formatting skipped ({reason})</em>"
112-
f"</span>"
113-
f"<pre>{preview}{suffix}</pre>"
114-
)
115-
116-
11794
def reformat_sql(sql, *, with_toggle=False):
118-
# Check length threshold to prevent slow formatting of large queries
119-
max_length = dt_settings.get_config()["SQL_PRETTIFY_MAX_LENGTH"]
120-
if max_length and len(sql) > max_length:
121-
skipped = _format_skipped_sql(
122-
sql,
123-
f"query length {len(sql):,} exceeds threshold {max_length:,}",
124-
)
125-
if with_toggle:
126-
# Return as non-collapsible since both versions would be the same
127-
return f'<span class="djDebugUncollapsed">{skipped}</span>'
128-
return skipped
129-
13095
formatted = parse_sql(sql)
13196
if not with_toggle:
13297
return formatted
13398
simplified = parse_sql(sql, simplify=True)
134-
13599
uncollapsed = f'<span class="djDebugUncollapsed">{simplified}</span>'
136100
collapsed = f'<span class="djDebugCollapsed djdt-hidden">{formatted}</span>'
137101
return collapsed + uncollapsed
138102

139103

140104
@lru_cache(maxsize=128)
141105
def parse_sql(sql, *, simplify=False):
106+
max_length = dt_settings.get_config()["PRETTIFY_SQL_MAX_LENGTH"]
107+
if max_length and len(sql) > max_length:
108+
return escape(sql, quote=False)
142109
stack = get_filter_stack(simplify=simplify)
143110
return "".join(stack.run(sql))
144111

debug_toolbar/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def _is_running_tests():
5050
"django.utils.functional",
5151
),
5252
"PRETTIFY_SQL": True,
53-
"SQL_PRETTIFY_MAX_LENGTH": 50000, # Skip formatting for SQL longer than this
53+
"PRETTIFY_SQL_MAX_LENGTH": 10000, # Skip formatting for SQL longer than this
5454
"PROFILER_CAPTURE_PROJECT_CODE": True,
5555
"PROFILER_MAX_DEPTH": 10,
5656
"PROFILER_THRESHOLD_RATIO": 8,

docs/changes.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ Change log
44
Pending
55
-------
66

7-
* Added ``SQL_PRETTIFY_MAX_LENGTH`` setting to skip SQL formatting for
8-
queries exceeding the threshold. This prevents the SQL panel from freezing
9-
or crashing when queries contain large IN clauses with thousands of
10-
parameters.
7+
* Added ``PRETTIFY_SQL_MAX_LENGTH`` setting to skip SQL formatting for
8+
queries exceeding the threshold (default: 10000, matching sqlparse's
9+
``MAX_GROUPING_TOKENS``). This prevents the SQL panel from freezing
10+
when queries contain large IN clauses with thousands of parameters.
1111
* Deprecated ``RedirectsPanel`` in favor of ``HistoryPanel`` for viewing
1212
toolbar data from redirected requests.
1313
* Fixed support for generating code coverage comments in PRs.

tests/panels/test_sql.py

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from debug_toolbar import settings as dt_settings
2020
from debug_toolbar.models import HistoryEntry
2121
from debug_toolbar.panels.sql import SQLPanel, tracking
22+
from debug_toolbar.panels.sql.utils import reformat_sql
2223

2324
try:
2425
import psycopg
@@ -870,48 +871,42 @@ def test_explain_with_union(self):
870871
self.assertTrue(query["is_select"])
871872

872873
@override_settings(
873-
DEBUG_TOOLBAR_CONFIG={"SQL_PRETTIFY_MAX_LENGTH": 100, "PRETTIFY_SQL": True}
874+
DEBUG_TOOLBAR_CONFIG={"PRETTIFY_SQL_MAX_LENGTH": 100, "PRETTIFY_SQL": True}
874875
)
875-
def test_sql_prettify_max_length(self):
876+
def test_prettify_sql_max_length(self):
876877
"""
877878
Test that SQL formatting is skipped for queries exceeding the max length threshold.
878879
"""
879-
from debug_toolbar.panels.sql.utils import reformat_sql
880-
881-
# Short SQL should be formatted normally
880+
# Short SQL should be formatted normally (includes <strong> tags for keywords)
882881
short_sql = "SELECT * FROM auth_user WHERE id = 1"
883882
result = reformat_sql(short_sql, with_toggle=True)
884-
self.assertNotIn("SQL formatting skipped", result)
885-
self.assertIn("SELECT", result)
883+
self.assertIn("<strong>", result)
886884

887-
# Long SQL should skip formatting and show a message
885+
# Long SQL should skip formatting (no <strong> tags, just escaped SQL)
888886
long_sql = (
889887
"SELECT * FROM auth_user WHERE id IN ("
890888
+ ", ".join([f"'{i}'" for i in range(100)])
891889
+ ")"
892890
)
893891
result = reformat_sql(long_sql, with_toggle=True)
894-
self.assertIn("SQL formatting skipped", result)
895-
self.assertIn("exceeds threshold", result)
892+
self.assertNotIn("<strong>", result)
893+
self.assertIn("SELECT", result)
896894

897-
def test_sql_prettify_max_length_disabled(self):
895+
@override_settings(
896+
DEBUG_TOOLBAR_CONFIG={"PRETTIFY_SQL_MAX_LENGTH": 0, "PRETTIFY_SQL": True}
897+
)
898+
def test_prettify_sql_max_length_disabled(self):
898899
"""
899-
Test that SQL_PRETTIFY_MAX_LENGTH=0 or None disables the length check.
900+
Test that PRETTIFY_SQL_MAX_LENGTH=0 disables the length check.
900901
"""
901-
from debug_toolbar.panels.sql.utils import reformat_sql
902-
903902
long_sql = (
904903
"SELECT * FROM auth_user WHERE id IN ("
905904
+ ", ".join([f"'{i}'" for i in range(100)])
906905
+ ")"
907906
)
908-
909-
with override_settings(
910-
DEBUG_TOOLBAR_CONFIG={"SQL_PRETTIFY_MAX_LENGTH": 0, "PRETTIFY_SQL": True}
911-
):
912-
result = reformat_sql(long_sql, with_toggle=True)
913-
# When max_length is 0 (falsy), formatting should not be skipped
914-
self.assertNotIn("SQL formatting skipped", result)
907+
result = reformat_sql(long_sql, with_toggle=True)
908+
# When max_length is 0 (falsy), formatting should not be skipped
909+
self.assertIn("<strong>", result)
915910

916911

917912
class SQLPanelMultiDBTestCase(BaseMultiDBTestCase):

0 commit comments

Comments
 (0)