Skip to content

Commit 5209cc7

Browse files
Ignore context tracking in SQL statements that are irrelevant or cause errors, like VACUUM (#232)
* Ignore context tracking in SQL statements that are irrelevant or cause errors, like VACUUM * fix release note
1 parent 19c1d2c commit 5209cc7

File tree

4 files changed

+44
-21
lines changed

4 files changed

+44
-21
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 3.8.3 (2025-09-23)
4+
5+
#### Fixes
6+
- Ignore context tracking on VACUUM and other SQL statements that are either irrelevant or cause issues by [@wesleykendall](https://github.com/wesleykendall) in [#232](https://github.com/AmbitionEng/django-pghistory/pull/232).
7+
38
## 3.8.2 (2025-09-12)
49

510
#### Fixes

pghistory/runtime.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,34 @@
2222

2323

2424
Context = collections.namedtuple("Context", ["id", "metadata"])
25-
26-
27-
def _is_concurrent_statement(sql: Union[str, bytes]):
25+
IGNORED_SQL_PREFIXES = (
26+
"select",
27+
"vacuum",
28+
"analyze",
29+
"checkpoint",
30+
"discard",
31+
"load",
32+
"cluster",
33+
"reindex",
34+
"create",
35+
"alter",
36+
"drop",
37+
)
38+
39+
40+
def _is_ignored_statement(sql: Union[str, bytes]):
2841
"""
29-
True if the sql statement is concurrent and cannot be ran in a transaction
30-
"""
31-
sql = sql.strip().lower() if sql else ""
32-
sql = sql.decode() if isinstance(sql, bytes) else sql
33-
return sql.startswith("create") and "concurrently" in sql
34-
42+
True if the sql statement is ignored for context tracking.
43+
This includes select statements and other statements like vacuum.
3544
36-
def _is_dml_statement(sql: Union[str, bytes]):
37-
"""
38-
True if the sql statement is a dml statement (insert, update, delete)
45+
Note: SQL is very complex. We may still inject context variables into
46+
SQL that has CTEs, for example. Generally this should handle most cases
47+
where it's impossible to even put a variable in the SQL, such as statements
48+
that cannot be ran in a transaction (vacuum, etc).
3949
"""
4050
sql = sql.strip().lower() if sql else ""
4151
sql = sql.decode() if isinstance(sql, bytes) else sql
42-
return not sql.startswith("select")
52+
return sql.startswith(IGNORED_SQL_PREFIXES)
4353

4454

4555
def _is_transaction_errored(cursor):
@@ -72,10 +82,9 @@ def _can_inject_variable(cursor, sql):
7282
setting. Ignore these cases for now.
7383
"""
7484
return (
75-
not getattr(cursor, "name", None)
76-
and not _is_concurrent_statement(sql)
85+
not _is_ignored_statement(sql)
86+
and not getattr(cursor, "name", None)
7787
and not _is_transaction_errored(cursor)
78-
and _is_dml_statement(sql)
7988
)
8089

8190

pghistory/tests/test_runtime.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@
99
"statement, expected",
1010
[
1111
("create index concurrently", True),
12-
("create index", False),
12+
("create index", True),
13+
("select * from auth_user", True),
14+
("vacuum table", True),
15+
("analyze table", True),
16+
("checkpoint table", True),
17+
("discard all", True),
18+
("load extension", True),
19+
("cluster", True),
20+
("update auth_user set id= %s where id = %s", False),
1321
(b"create index concurrently", True),
14-
(b"create index", False),
22+
(b"select * from auth_user", True),
23+
(b"update auth_user set id= %s where id = %s", False),
1524
],
1625
)
17-
def test_is_concurrent_statement(statement, expected):
18-
assert pghistory.runtime._is_concurrent_statement(statement) == expected
26+
def test_is_ignored_statement(statement, expected):
27+
assert pghistory.runtime._is_ignored_statement(statement) == expected
1928

2029

2130
@pytest.mark.skipif(

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ packages = [
3030
exclude = [
3131
"*/tests/"
3232
]
33-
version = "3.8.2"
33+
version = "3.8.3"
3434
description = "History tracking for Django and Postgres"
3535
authors = ["Wes Kendall"]
3636
classifiers = [

0 commit comments

Comments
 (0)