Repository: adamchainz/django-perf-rec

Issue:
Regression in 4.8.0 for behaviour introduced in 4.6.0
Hi Adam, we've noticed that in 4.8.0 (#306) when sqlparse was upgraded, the fix we submitted that was included in 4.6.0 (#263) stopped working and the tests were reverted.

Was there a reason why the behaviour is no longer possible? Or was there a decision that it was not the desired behaviour?

We're keen to fix this again as it's causing us some pain having upgraded the library, but want to make sure we have full context before going ahead.


Discussion:
Complete accident/oversight when the test failed after upgrading.

Resolving patch:
diff --git a/src/django_perf_rec/sql.py b/src/django_perf_rec/sql.py
--- a/src/django_perf_rec/sql.py
+++ b/src/django_perf_rec/sql.py
@@ -1,7 +1,7 @@
 from functools import lru_cache
 
 from sqlparse import parse, tokens
-from sqlparse.sql import Comment, IdentifierList, Parenthesis, Token
+from sqlparse.sql import Comment, Comparison, IdentifierList, Parenthesis, Token
 
 
 @lru_cache(maxsize=500)
@@ -87,19 +87,19 @@ def sql_recursively_simplify(node, hide_columns=True):
         node.tokens = node.tokens[: i_set + 1] + middle + end
 
     # Ensure IN clauses with simple value in always simplify to "..."
-    if node.tokens[0].value == "WHERE":
-        in_token_indices = (i for i, t in enumerate(node.tokens) if t.value == "IN")
-        for in_token_index in in_token_indices:
-            parenthesis = next(
-                t
-                for t in node.tokens[in_token_index + 1 :]
-                if isinstance(t, Parenthesis)
-            )
-            if all(
-                getattr(t, "ttype", "") in sql_deleteable_tokens
-                for t in parenthesis.tokens[1:-1]
-            ):
-                parenthesis.tokens[1:-1] = [Token(tokens.Punctuation, "...")]
+    if (
+        isinstance(node, Comparison)
+        and hasattr(node, "tokens")
+        and len(node.tokens) == 5
+        and node.tokens[2].value.lower() == "in"
+        and isinstance(node.tokens[4], Parenthesis)
+    ):
+        parenthesis = node.tokens[4]
+        if all(
+            getattr(t, "ttype", "") in sql_deleteable_tokens
+            for t in parenthesis.tokens[1:-1]
+        ):
+            parenthesis.tokens[1:-1] = [Token(tokens.Punctuation, "...")]
 
     # Erase the names of savepoints since they are non-deteriministic
     if hasattr(node, "tokens"):


Test patch:
diff --git a/tests/test_api.perf.yml b/tests/test_api.perf.yml
--- a/tests/test_api.perf.yml
+++ b/tests/test_api.perf.yml
@@ -1,8 +1,8 @@
 RecordTests.test_delete_on_cascade_called_twice:
-- db: DELETE FROM "testapp_book" WHERE "testapp_book"."author_id" IN (#)
-- db: DELETE FROM "testapp_award" WHERE "testapp_award"."author_id" IN (#)
-- db: DELETE FROM "testapp_contract_author" WHERE "testapp_contract_author"."author_id" IN (#)
-- db: DELETE FROM "testapp_author" WHERE "testapp_author"."id" IN (#)
+- db: DELETE FROM "testapp_book" WHERE "testapp_book"."author_id" IN (...)
+- db: DELETE FROM "testapp_award" WHERE "testapp_award"."author_id" IN (...)
+- db: DELETE FROM "testapp_contract_author" WHERE "testapp_contract_author"."author_id" IN (...)
+- db: DELETE FROM "testapp_author" WHERE "testapp_author"."id" IN (...)
 RecordTests.test_dependent_QuerySet_annotate:
 - db: SELECT ... FROM "testapp_author"
 RecordTests.test_get_or_set:
@@ -37,6 +37,9 @@ RecordTests.test_single_db_query_model_with_columns:
 RecordTests.test_single_db_query_with_filtering: []
 RecordTests.test_single_db_query_with_filtering.2:
 - db: 'SELECT #'
+RecordTests.test_single_db_query_with_filtering_negative: []
+RecordTests.test_single_db_query_with_filtering_positive:
+- db: 'SELECT #'
 TestCaseMixinTests.test_record_performance:
 - cache|get: foo
 custom:
diff --git a/tests/test_sql.py b/tests/test_sql.py
--- a/tests/test_sql.py
+++ b/tests/test_sql.py
@@ -281,7 +281,7 @@ def test_strip_raw_query():
 def test_in_single_value():
     assert (
         sql_fingerprint("SELECT `f1`, `f2` FROM `b` WHERE `x` IN (1)")
-        == "SELECT ... FROM `b` WHERE `x` IN (#)"
+        == "SELECT ... FROM `b` WHERE `x` IN (...)"
     )