Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions debug_toolbar/panels/sql/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,26 @@ def is_select_query(sql):


def reformat_sql(sql, *, with_toggle=False):
formatted = parse_sql(sql)
import logging

logger = logging.getLogger(__name__)

# Try to format the full SQL
try:
formatted = parse_sql(sql)
except (sqlparse.exceptions.SQLParseError, RecursionError) as e:
logger.warning(f"Failed to format SQL query: {e}")
formatted = f"-- SQL formatting failed (query too large)\n{sql}"

if not with_toggle:
return formatted
simplified = parse_sql(sql, simplify=True)

try:
simplified = parse_sql(sql, simplify=True)
except (sqlparse.exceptions.SQLParseError, RecursionError) as e:
logger.warning(f"Failed to simplify SQL query: {e}")
simplified = f"-- Simplified formatting failed\n{sql}"

uncollapsed = f'<span class="djDebugUncollapsed">{simplified}</span>'
collapsed = f'<span class="djDebugCollapsed djdt-hidden">{formatted}</span>'
return collapsed + uncollapsed
Expand Down
42 changes: 42 additions & 0 deletions tests/test_sql_large_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import pytest

from debug_toolbar.panels.sql.utils import reformat_sql


def test_reformat_sql_with_huge_in_clause():
"""Test that huge IN clauses don't cause crashes"""
# Create a SQL with a huge IN clause (5000 items)
items = [f"'{i}'" for i in range(5000)]
sql = f"SELECT * FROM table WHERE id IN ({','.join(items)})"

# This should not raise an exception
try:
result = reformat_sql(sql, with_toggle=False)
assert isinstance(result, str)
assert len(result) > 0
except Exception as e:
pytest.fail(f"reformat_sql raised {type(e).__name__}: {e}")


def test_reformat_sql_with_toggle_and_huge_in_clause():
"""Test with_toggle=True with huge IN clause"""
items = [f"'{i}'" for i in range(5000)]
sql = f"SELECT * FROM table WHERE id IN ({','.join(items)})"

try:
result = reformat_sql(sql, with_toggle=True)
assert isinstance(result, str)
assert "djDebugUncollapsed" in result
assert "djDebugCollapsed" in result
except Exception as e:
pytest.fail(f"reformat_sql (with_toggle) raised {type(e).__name__}: {e}")


def test_reformat_sql_with_invalid_sql():
"""Test that invalid SQL is handled gracefully"""
sql = "SELECT * FROM WHERE" # Invalid SQL

result = reformat_sql(sql, with_toggle=False)
assert isinstance(result, str)
# Should either contain the SQL or an error message
assert len(result) > 0