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 Initial Version

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

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):  
    11711171                with self.assertRaisesMessage(ValueError, msg):
    11721172                    Book.objects.annotate(**{crafted_alias: Value(1)})
    11731173
     1174    def test_annotation_contains_percent(self):
     1175        Book.objects.annotate(**{"contains_percent%": F("pk")}).first()
     1176
    11741177    @skipUnless(connection.vendor == "postgresql", "PostgreSQL tests")
    11751178    @skipUnlessDBFeature("supports_json_field")
    11761179    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.

The Oracle backend does this for you.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top