Opened 3 days ago
Last modified 2 days ago
#36152 new Cleanup/optimization
Postgres backend could quote `%` in column aliases instead of failing at the db level — at Version 1
Reported by: | Jacob Walls | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When developing with postgres, if you are creating dynamic annotations, you have to know to reject %
in the provided alias or transform it to %%
, otherwise you end up with an unhelpful exception from the db adapter.
test case:
-
tests/annotations/tests.py
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py index 29660a827e..6bc9bc9ed4 100644
a b class NonAggregateAnnotationTestCase(TestCase): 1171 1171 with self.assertRaisesMessage(ValueError, msg): 1172 1172 Book.objects.annotate(**{crafted_alias: Value(1)}) 1173 1173 1174 def test_annotation_contains_percent(self): 1175 Book.objects.annotate(**{"contains_percent%": F("pk")}).first() 1176 1174 1177 @skipUnless(connection.vendor == "postgresql", "PostgreSQL tests") 1175 1178 @skipUnlessDBFeature("supports_json_field") 1176 1179 def test_set_returning_functions(self):
Gives on psycopg2:
IndexError: tuple index out of range
On psycopg 3, the errors are more helpful, either:
django.db.utils.ProgrammingError: only '%s', '%b', '%t' are allowed as placeholders, got '%"'
Or if the annotation indeed included %s:
django.db.utils.ProgrammingError: the query has 2 placeholders but 1 parameters were passed
But I still think we could easily fail at the ORM level instead of going to the backend and failing there just quote %
to %%
.
The Oracle backend does this for you.