diff options
| author | Rob Hudson | 2008-10-06 13:53:14 -0700 | 
|---|---|---|
| committer | Rob Hudson | 2008-10-06 13:53:46 -0700 | 
| commit | a3492e14765e3f898efc26913a8e8c4445a837b4 (patch) | |
| tree | d171c7310fec4c71b39f38cfbbcd463401d2f9f2 | |
| parent | e9271bf69ab50cb24e38ac2205847c8d32b83ca8 (diff) | |
| download | django-debug-toolbar-a3492e14765e3f898efc26913a8e8c4445a837b4.tar.bz2 | |
Adding query profiling for MySQL.  Thanks to Simon Willison for the suggestion.
There's a big TODO on this one, which is to not display or attempt to execute
the profiling SQL calls if this isn't MySQL and if MySQL isn't >= version
5.0.37.  For now it's a nice playground of the profiler if you have MySQL
v5.0.37 or higher.
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/sql.html | 1 | ||||
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/sql_profile.html | 26 | ||||
| -rw-r--r-- | debug_toolbar/urls.py | 1 | ||||
| -rw-r--r-- | debug_toolbar/views.py | 35 | 
4 files changed, 63 insertions, 0 deletions
| diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 2abb68f..d35d83e 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -15,6 +15,7 @@  				{% if query.params %}  					<a class="remoteCall" href="/__debug__/sql_select/?sql={{ query.raw_sql|urlencode }}¶ms={{ query.params|urlencode }}&time={{ query.time|floatformat:"4"|urlencode }}&hash={{ query.hash }}">SELECT</a>  					<a class="remoteCall" href="/__debug__/sql_explain/?sql={{ query.raw_sql|urlencode }}¶ms={{ query.params|urlencode }}&time={{ query.time|floatformat:"4"|urlencode }}&hash={{ query.hash }}">EXPLAIN</a> +					<a class="remoteCall" href="/__debug__/sql_profile/?sql={{ query.raw_sql|urlencode }}¶ms={{ query.params|urlencode }}&time={{ query.time|floatformat:"4"|urlencode }}&hash={{ query.hash }}">PROFILE</a>  				{% endif %}  				</td>  				<td class="syntax">{{ query.sql|safe }}</td> diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql_profile.html b/debug_toolbar/templates/debug_toolbar/panels/sql_profile.html new file mode 100644 index 0000000..c1d04ce --- /dev/null +++ b/debug_toolbar/templates/debug_toolbar/panels/sql_profile.html @@ -0,0 +1,26 @@ +<a class="back" href="">« Back</a> +<h3>SQL Profiled</h3> +<dl> +	<dt>Executed SQL</dt> +	<dd><pre>{{ sql|safe }}</pre></dd> +	<dt>Time</dt> +	<dd>{{ time }} ms</dd> +</dl> +<table> +	<thead> +		<tr> +			{% for h in headers %} +				<th>{{ h|upper }}</th> +			{% endfor %} +		</tr> +	</thead> +	<tbody> +		{% for row in result %} +			<tr class="{% cycle 'odd' 'even' %}"> +				{% for column in row %} +					<td>{{ column|escape }}</td> +				{% endfor %} +			</tr> +		{% endfor %} +	</tbody> +</table> diff --git a/debug_toolbar/urls.py b/debug_toolbar/urls.py index 437d36b..53a426b 100644 --- a/debug_toolbar/urls.py +++ b/debug_toolbar/urls.py @@ -11,4 +11,5 @@ urlpatterns = patterns('',      url(r'^__debug__/m/(.*)$', 'debug_toolbar.views.debug_media'),      url(r'^__debug__/sql_select/$', 'debug_toolbar.views.sql_select', name='sql_select'),      url(r'^__debug__/sql_explain/$', 'debug_toolbar.views.sql_explain', name='sql_explain'), +    url(r'^__debug__/sql_profile/$', 'debug_toolbar.views.sql_profile', name='sql_profile'),  ) diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py index 4b666e1..8af879f 100644 --- a/debug_toolbar/views.py +++ b/debug_toolbar/views.py @@ -81,3 +81,38 @@ def sql_explain(request):              'headers': headers,          }          return render_to_response('debug_toolbar/panels/sql_explain.html', context) + +def sql_profile(request): +    """ +    Returns the output of running the SQL and getting the profiling statistics. + +    Expected GET variables: +        sql: urlencoded sql with positional arguments +        params: JSON encoded parameter values +        time: time for SQL to execute passed in from toolbar just for redisplay +        hash: the hash of (secret + sql + params) for tamper checking +    """ +    from debug_toolbar.panels.sql import reformat_sql +    sql = request.GET.get('sql', '') +    params = request.GET.get('params', '') +    hash = sha_constructor(settings.SECRET_KEY + sql + params).hexdigest() +    if hash != request.GET.get('hash', ''): +        return HttpResponse('<h3>Tamper alert</h3>') # SQL Tampering alert +    if sql.lower().startswith('select'): +        params = simplejson.loads(params) +        cursor = connection.cursor() +        cursor.execute("SET PROFILING=1") # Enable profiling +        cursor.execute(sql, params) # Execute SELECT +        cursor.execute("SET PROFILING=0") # Disable profiling +        # The Query ID should always be 1 here but I'll subselect to get the last one just in case... +        cursor.execute("SELECT * FROM information_schema.profiling WHERE query_id=(SELECT query_id FROM information_schema.profiling ORDER BY query_id DESC LIMIT 1)") +        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) | 
