From 4ef51f1c912d49c7650126398c4ac38fef0f795c Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Thu, 11 Sep 2008 23:18:14 -0700 Subject: Moving reformat sql so we can pull this in elsewhere. --- debug_toolbar/panels/sql.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index f23e317..8edfce9 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -36,13 +36,6 @@ class SQLDebugPanel(DebugPanel): self._offset = len(connection.queries) self._sql_time = 0 - def _reformat_sql(self, sql): - sql = sql.replace('`,`', '`, `') - sql = sql.replace('` FROM `', '` \n FROM `') - sql = sql.replace('` WHERE ', '` \n WHERE ') - sql = sql.replace(' ORDER BY ', ' \n ORDER BY ') - return sql - def title(self): self._sql_time = sum(map(lambda q: float(q['time']) * 1000, connection.queries)) return '%d SQL Queries (%.2fms)' % (len(connection.queries), self._sql_time) @@ -53,10 +46,19 @@ class SQLDebugPanel(DebugPanel): def content(self): sql_queries = connection.queries[self._offset:] for query in sql_queries: - query['sql'] = self._reformat_sql(query['sql']) + query['sql'] = reformat_sql(query['sql']) context = { 'queries': sql_queries, 'sql_time': self._sql_time, } return render_to_string('debug_toolbar/panels/sql.html', context) + +def reformat_sql(sql): + sql = sql.replace('`,`', '`, `') + sql = sql.replace('` FROM `', '` \n FROM `') + sql = sql.replace('` WHERE ', '` \n WHERE ') + sql = sql.replace('` INNER JOIN ', '` \n INNER JOIN ') + sql = sql.replace('` OUTER JOIN ', '` \n OUTER JOIN ') + sql = sql.replace(' ORDER BY ', ' \n ORDER BY ') + return sql -- cgit v1.2.3 From 8377ea179568c1fbf8f46db1234e85d689daae0a Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Thu, 11 Sep 2008 23:19:27 -0700 Subject: Adding JSON params to pass to view and adding link for explain. --- debug_toolbar/panels/sql.py | 3 ++- debug_toolbar/templates/debug_toolbar/panels/sql.html | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 8edfce9..757505a 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -1,3 +1,4 @@ +import simplejson import time from debug_toolbar.panels import DebugPanel from django.db import connection @@ -20,7 +21,7 @@ class DatabaseStatTracker(util.CursorDebugWrapper): 'sql': self.db.ops.last_executed_query(self.cursor, sql, params), 'time': stop - start, 'raw_sql': sql, - 'params': params, + 'params': simplejson.dumps(params), }) util.CursorDebugWrapper = DatabaseStatTracker diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 046be7f..9a6638b 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -4,13 +4,15 @@ Time (ms) Query + Action {% for query in queries %} {{ query.time|floatformat:"4" }} -
{{ query.sql|escape }}
+
{{ query.sql|wordwrap:80|escape }}
+ EXPLAIN {% endfor %} -- cgit v1.2.3 From 4591e34f0140c43e68e4ecd97eae7f3ea05878f6 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Thu, 11 Sep 2008 23:21:12 -0700 Subject: Adding view to explain SQL passed in via query string. Hopefully this is database backend agnostic. Next up is connecting this with the SQL panel via AJAX. --- .../debug_toolbar/panels/sql_explain.html | 25 ++++++++++++++++++ debug_toolbar/urls.py | 6 +++++ debug_toolbar/views.py | 30 ++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 debug_toolbar/templates/debug_toolbar/panels/sql_explain.html create mode 100644 debug_toolbar/urls.py create mode 100644 debug_toolbar/views.py diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql_explain.html b/debug_toolbar/templates/debug_toolbar/panels/sql_explain.html new file mode 100644 index 0000000..757d43f --- /dev/null +++ b/debug_toolbar/templates/debug_toolbar/panels/sql_explain.html @@ -0,0 +1,25 @@ +

SQL Explained

+
+
Executed SQL
+
{{ sql|wordwrap:80 }}
+
Time
+
{{ time }} ms
+
+ + + + {% for h in headers %} + + {% endfor %} + + + + {% for row in result %} + + {% for column in row %} + + {% endfor %} + + {% endfor %} + +
{{ h|upper }}
{{ column|escape }}
diff --git a/debug_toolbar/urls.py b/debug_toolbar/urls.py new file mode 100644 index 0000000..24d4b12 --- /dev/null +++ b/debug_toolbar/urls.py @@ -0,0 +1,6 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', + # EXPLAIN SQL via AJAX + url(r'explain/$', 'debug_toolbar.views.explain', name='explain_sql'), +) diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py new file mode 100644 index 0000000..5bdf450 --- /dev/null +++ b/debug_toolbar/views.py @@ -0,0 +1,30 @@ +import simplejson +from django.db import connection +from django.shortcuts import render_to_response +from debug_toolbar.panels.sql import reformat_sql + +def explain(request): + """ + Returns the output of the SQL EXPLAIN on the given query. + + Expected GET variables: + sql: urlencoded sql with position arguments + params: JSON encoded parameter values + time: time for SQL to execute passed in from toolbar just for redisplay + """ + sql = request.GET.get('sql', '') + if sql.lower().startswith('select'): + params = simplejson.loads(request.GET.get('params', '')) + cursor = connection.cursor() + cursor.execute("EXPLAIN %s" % (sql,), params) + headers = [d[0] for d in cursor.description] + result = cursor.fetchall() + cursor.close() + context = { + 'result': result, + 'sql': reformat_sql(cursor.db.ops.last_executed_query(cursor, sql, params)), + 'time': request.GET.get('time', 0.0), + 'headers': headers, + } + return render_to_response('debug_toolbar/panels/sql_explain.html', context) + \ No newline at end of file -- cgit v1.2.3 From 43bb25c874f765800076285e76b2b0ba1460a597 Mon Sep 17 00:00:00 2001 From: Nowell Strite Date: Fri, 19 Sep 2008 01:17:16 -0400 Subject: Fixed template panel to skip over debug_toolbar templates. Fixed a bug in template context output where rendering would hang while trying to autoescape the context variable output. --- debug_toolbar/panels/template.py | 3 +++ debug_toolbar/templates/debug_toolbar/panels/templates.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index f02b673..bda6630 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -50,6 +50,9 @@ class TemplateDebugPanel(DebugPanel): info = {} # Clean up some info about templates t = d.get('template', None) + # Skip templates that we are generating through the debug toolbar. + if t.name.startswith('debug_toolbar/'): + continue if t.origin and t.origin.name: t.origin_name = t.origin.name else: diff --git a/debug_toolbar/templates/debug_toolbar/panels/templates.html b/debug_toolbar/templates/debug_toolbar/panels/templates.html index ee93708..0c47c5c 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/templates.html +++ b/debug_toolbar/templates/debug_toolbar/panels/templates.html @@ -16,7 +16,7 @@
{{ template.template.origin_name|addslashes }}
Toggle Context
- +
{% endfor %} -- cgit v1.2.3 From 5a711759e75bfef4788498d9cfaa9fe019bcd15d Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Fri, 19 Sep 2008 10:47:16 -0700 Subject: Remove the safe filter from template context so objects don't turn into HTML tags (e.g. ) --- debug_toolbar/templates/debug_toolbar/panels/templates.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/templates/debug_toolbar/panels/templates.html b/debug_toolbar/templates/debug_toolbar/panels/templates.html index 0c47c5c..575d507 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/templates.html +++ b/debug_toolbar/templates/debug_toolbar/panels/templates.html @@ -16,10 +16,10 @@
{{ template.template.origin_name|addslashes }}
- +
{% endfor %} {% else %} None -{% endif %} \ No newline at end of file +{% endif %} -- cgit v1.2.3