Prevent TypeError when bytes passed to cursor.execute in debug middleware

If DjangoDebugMiddleware is installed, calling `cursor.execute(b)` where b is a `bytes` object causes the recording (and thus the entire database call) to throw a TypeError due to 775644b536/graphene_django/debug/sql/tracking.py (L126) :

```
"is_select": sql.lower().strip().startswith("select"),
```

Calling execute with a bytes parameter, to my knowledge, is not currently done within the high-level abstractions in the Django ORM, but is very much supported by psycopg2, as evidenced by the use in psycopg2's own `execute_values` in https://github.com/psycopg/psycopg2/blob/2_9_3/lib/extras.py#L1270 :

```
cur.execute(b''.join(parts))
```

This fix ensures that the sql parameter is safely decoded before scanning whether it begins with SELECT; since this is the only usage, the change is trivial.

The only workaround if code calls execute_values is to disable the DjangoDebugMiddleware altogether, which is far from ideal.
This commit is contained in:
Brenton Partridge 2022-02-09 18:07:48 -08:00
parent e8f36b018d
commit 7365ee3ec9

View File

@ -109,6 +109,7 @@ class NormalCursorWrapper:
alias = getattr(self.db, "alias", "default") alias = getattr(self.db, "alias", "default")
conn = self.db.connection conn = self.db.connection
vendor = getattr(conn, "vendor", "unknown") vendor = getattr(conn, "vendor", "unknown")
sql_str = sql.decode(errors="ignore") if isinstance(sql, bytes) else sql
params = { params = {
"vendor": vendor, "vendor": vendor,
@ -122,7 +123,7 @@ class NormalCursorWrapper:
"start_time": start_time, "start_time": start_time,
"stop_time": stop_time, "stop_time": stop_time,
"is_slow": duration > 10, "is_slow": duration > 10,
"is_select": sql.lower().strip().startswith("select"), "is_select": sql_str.lower().strip().startswith("select"),
} }
if vendor == "postgresql": if vendor == "postgresql":