From cf56183fb2dc382bfe227908eb331f3c44551a3d Mon Sep 17 00:00:00 2001 From: Brian Davis Date: Thu, 15 Nov 2018 10:50:42 -0600 Subject: [PATCH 1/3] Handle psycopg2's string composition --- sentry_sdk/integrations/django/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index b28303868d..2148b4941d 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -7,6 +7,19 @@ from django import VERSION as DJANGO_VERSION from django.core import signals +try: + import psycopg2.sql + + def sql_to_string(sql): + if isinstance(sql, psycopg2.sql.SQL): + return sql.string + return sql +except ImportError: + def sql_to_string(sql): + return sql + +import psycopg2.sql + try: from django.urls import resolve except ImportError: @@ -203,6 +216,7 @@ def format_sql(sql, params): # convert sql with named parameters to sql with unnamed parameters conv = _FormatConverter(params) if params: + sql = sql_to_string(sql) sql = sql % conv params = conv.params else: From d820d9100c1309c3aea4bea96d5e209f5337062f Mon Sep 17 00:00:00 2001 From: Brian Davis Date: Thu, 15 Nov 2018 11:44:47 -0600 Subject: [PATCH 2/3] Remove extraneous import --- sentry_sdk/integrations/django/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 2148b4941d..0c69ebd13a 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -18,8 +18,6 @@ def sql_to_string(sql): def sql_to_string(sql): return sql -import psycopg2.sql - try: from django.urls import resolve except ImportError: From 8060afdb9f89d50c1e742b83b43b924c5d1af246 Mon Sep 17 00:00:00 2001 From: Brian Davis Date: Thu, 15 Nov 2018 12:55:48 -0600 Subject: [PATCH 3/3] Add tests, run black --- sentry_sdk/integrations/django/__init__.py | 4 ++ tests/integrations/django/test_basic.py | 46 ++++++++++++++++++++++ tox.ini | 2 + 3 files changed, 52 insertions(+) diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 0c69ebd13a..85cd7b18f9 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -14,10 +14,14 @@ def sql_to_string(sql): if isinstance(sql, psycopg2.sql.SQL): return sql.string return sql + + except ImportError: + def sql_to_string(sql): return sql + try: from django.urls import resolve except ImportError: diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 5fe6fe0bdd..6abc72fdc5 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -141,6 +141,52 @@ def test_sql_queries(sentry_init, capture_events): assert crumb["message"] == """SELECT count(*) FROM people_person WHERE foo = 123""" +@pytest.mark.django_db +def test_sql_dict_query_params(sentry_init, capture_events): + sentry_init(integrations=[DjangoIntegration()], send_default_pii=True) + from django.db import connection + + sql = connection.cursor() + + events = capture_events() + with pytest.raises(Exception): + # table doesn't even exist + sql.execute( + """SELECT count(*) FROM people_person WHERE foo = %(my_foo)s""", + {"my_foo": 10}, + ) + + capture_message("HI") + + event, = events + + crumb, = event["breadcrumbs"] + assert crumb["message"] == ("SELECT count(*) FROM people_person WHERE foo = 10") + + +@pytest.mark.django_db +def test_sql_psycopg2_string_composition(sentry_init, capture_events): + sentry_init(integrations=[DjangoIntegration()], send_default_pii=True) + from django.db import connection + from psycopg2 import sql as psycopg2_sql + + sql = connection.cursor() + + events = capture_events() + with pytest.raises(Exception): + # table doesn't even exist + sql.execute( + psycopg2_sql.SQL("SELECT %(my_param)s FROM people_person"), {"my_param": 10} + ) + + capture_message("HI") + + event, = events + + crumb, = event["breadcrumbs"] + assert crumb["message"] == ("SELECT 10 FROM people_person") + + @pytest.mark.django_db def test_sql_queries_large_params(sentry_init, capture_events): sentry_init(integrations=[DjangoIntegration()], send_default_pii=True) diff --git a/tox.ini b/tox.ini index d3465c7950..12760f3da9 100644 --- a/tox.ini +++ b/tox.ini @@ -42,6 +42,8 @@ envlist = deps = -r test-requirements.txt + django: psycopg2>=2.7.5 + django-{1.6,1.7,1.8}: pytest-django<3.0 django-{1.9,1.10,1.11,2.0,2.1,dev}: pytest-django>=3.0 django-1.6: Django>=1.6,<1.7