Repository: jazzband/django-debug-toolbar

Issue:
500 Error on Explaining Postgres query with JSONB
![screen shot 2017-10-27 at 8 52 58 am](https://user-images.githubusercontent.com/2790092/32104864-41ea898e-baf4-11e7-8aa7-22c990592a1c.png)

query:

```SQL
SELECT (data->'game'->'id') AS "game_id", (data->'game'->'date') AS "game_date", (data->'game'->'workflowStatus') AS "workflow_status", "core_item"."id", "core_item"."name", "core_item"."source", "core_item"."pointer", "core_item"."label", "core_item"."story_type_id", "core_item"."updated_at", "core_item"."created_at" FROM "core_item" INNER JOIN "core_storytype" ON ("core_item"."story_type_id" = "core_storytype"."id") INNER JOIN "core_project" ON ("core_storytype"."project_id" = "core_project"."id") WHERE ("core_project"."name" = 'hss' AND "core_storytype"."name" = 'FootballGame' AND "core_item"."label" = 'prod' AND ("core_item"."data" #> ARRAY['game', 'workflowStatus']) = '"APPROVED"') ORDER BY "core_item"."updated_at" DESC, "core_item"."id" DESC LIMIT 100
```

Clicking Explain gives a "500: Internal Server Error".

Traceback:

```
Internal Server Error: /__debug__/sql_explain/
Traceback (most recent call last):
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
psycopg2.DataError: malformed array literal: "['game', 'workflowStatus']"
LINE 1: ...item"."label" = 'prod' AND ("core_item"."data" #> '[''game''...
                                                             ^
DETAIL:  "[" must introduce explicitly-specified array dimensions.


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/debug_toolbar/decorators.py", line 15, in inner
    return view(request, *args, **kwargs)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/debug_toolbar/panels/sql/views.py", line 55, in sql_explain
    cursor.execute("EXPLAIN ANALYZE %s" % (sql,), params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 80, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/raven/contrib/django/client.py", line 114, in execute
    return real_execute(self, sql, params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
django.db.utils.DataError: malformed array literal: "['game', 'workflowStatus']"
LINE 1: ...item"."label" = 'prod' AND ("core_item"."data" #> '[''game''...
                                                             ^
DETAIL:  "[" must introduce explicitly-specified array dimensions.

[django.request] 2017-10-27 12:54:48,040 Internal Server Error: /__debug__/sql_explain/
Traceback (most recent call last):
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
psycopg2.DataError: malformed array literal: "['game', 'workflowStatus']"
LINE 1: ...item"."label" = 'prod' AND ("core_item"."data" #> '[''game''...
                                                             ^
DETAIL:  "[" must introduce explicitly-specified array dimensions.


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/debug_toolbar/decorators.py", line 15, in inner
    return view(request, *args, **kwargs)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/debug_toolbar/panels/sql/views.py", line 55, in sql_explain
    cursor.execute("EXPLAIN ANALYZE %s" % (sql,), params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 80, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/raven/contrib/django/client.py", line 114, in execute
    return real_execute(self, sql, params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/Users/johria/.local/share/virtualenvs/api-IzJWx2po/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
django.db.utils.DataError: malformed array literal: "['game', 'workflowStatus']"
LINE 1: ...item"."label" = 'prod' AND ("core_item"."data" #> '[''game''...
                                                             ^
DETAIL:  "[" must introduce explicitly-specified array dimensions.

[27/Oct/2017 12:54:48] "POST /__debug__/sql_explain/ HTTP/1.1" 500 8382
```


Discussion:
might be related to https://github.com/jazzband/django-debug-toolbar/issues/796

Resolving patch:
diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py
--- a/debug_toolbar/panels/sql/tracking.py
+++ b/debug_toolbar/panels/sql/tracking.py
@@ -96,6 +96,14 @@ def _quote_params(self, params):
         return [self._quote_expr(p) for p in params]
 
     def _decode(self, param):
+        # If a sequence type, decode each element separately
+        if isinstance(param, list) or isinstance(param, tuple):
+            return [self._decode(element) for element in param]
+
+        # If a dictionary type, decode each value separately
+        if isinstance(param, dict):
+            return {key: self._decode(value) for key, value in param.items()}
+
         # make sure datetime, date and time are converted to string by force_text
         CONVERT_TYPES = (datetime.datetime, datetime.date, datetime.time)
         try:


Test patch: