Opened 7 days ago

Closed 4 days ago

#36326 closed New feature (fixed)

Add support for CompositePrimaryKey in QuerySet.raw()

Reported by: Adam Johnson Owned by: JaeHyuckSa
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Csirmaz Bendegúz, Simon Charette Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

Currently, a check in RawModelIterable fails for models with a CompositePrimaryKey.

For example, this model:

class AuthorEvent(models.Model):
    timestamp = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    pk = models.CompositePrimaryKey(
        "author",
        "timestamp",
    )

fails like:

In [2]: list(AuthorEvent.objects.raw("SELECT * FROM example_authorevent"))
---------------------------------------------------------------------------
FieldDoesNotExist                         Traceback (most recent call last)
Cell In[2], line 1
----> 1 list(AuthorEvent.objects.raw("SELECT * FROM example_authorevent"))

File ..../django/db/models/query.py:2133, in RawQuerySet.__iter__(self)
   2132 def __iter__(self):
-> 2133     self._fetch_all()
   2134     return iter(self._result_cache)

File ..../django/db/models/query.py:2120, in RawQuerySet._fetch_all(self)
   2118 def _fetch_all(self):
   2119     if self._result_cache is None:
-> 2120         self._result_cache = list(self.iterator())
   2121     if self._prefetch_related_lookups and not self._prefetch_done:
   2122         self._prefetch_related_objects()

File ..../django/db/models/query.py:2147, in RawQuerySet.iterator(self)
   2146 def iterator(self):
-> 2147     yield from RawModelIterable(self)

File ..../django/db/models/query.py:169, in RawModelIterable.__iter__(self)
    167 model_cls = self.queryset.model
    168 if model_cls._meta.pk.attname not in model_init_names:
--> 169     raise exceptions.FieldDoesNotExist(
    170         "Raw query must include the primary key"
    171     )
    172 fields = [self.queryset.model_fields.get(c) for c in self.queryset.columns]
    173 cols = [f.get_col(f.model._meta.db_table) if f else None for f in fields]

FieldDoesNotExist: Raw query must include the primary key

To add support, we should add a test, update this check to look for all columns in the PK, and fix anything else as necessary.

Change History (7)

comment:1 by Sarah Boyce, 7 days ago

Cc: Csirmaz Bendegúz Simon Charette added
Triage Stage: UnreviewedAccepted
Type: BugNew feature

Thank you for the report!
I've marked this as a new feature to add support but I can be persuaded to have this as a release blocking bug

Replicated:

  • TabularUnified tests/composite_pk/tests.py

    a b class CompositePKTests(TestCase):  
    158158        users = User.objects.values_list("pk").order_by("pk")
    159159        self.assertNotIn('AS "pk"', str(users.query))
    160160
     161    def test_raw(self):
     162        users = User.objects.raw("SELECT * FROM composite_pk_user")
     163        self.assertEqual(len(users), 1)
     164
    161165    def test_only(self):
    162166        users = User.objects.only("pk")
    163167        self.assertSequenceEqual(users, (self.user,))

comment:2 by Csirmaz Bendegúz, 7 days ago

Easy pickings: set

thanks for the cc! I see, we have overlooked raw queries. I wasn't aware of this check there

agreed it's not release blocking, but it does feel like a bug

it should be an easy fix, marking it as "easy pickings" in case a newcomer wants to pick it up

comment:3 by JaeHyuckSa, 7 days ago

Owner: set to JaeHyuckSa
Status: newassigned

comment:4 by Adam Johnson, 7 days ago

Yeah, I wouldn't make this a release blocker, just another "extra support" feature ticket :)

comment:5 by JaeHyuckSa, 7 days ago

Has patch: set

comment:6 by Sarah Boyce, 5 days ago

Triage Stage: AcceptedReady for checkin

comment:7 by Sarah Boyce <42296566+sarahboyce@…>, 4 days ago

Resolution: fixed
Status: assignedclosed

In 1831f77:

Fixed #36326 -- Added CompositePrimaryKey support in QuerySet.raw().

Signed-off-by: SaJH <wogur981208@…>

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