#36416 closed Bug (fixed)
id_list argument to in_bulk() does not account for composite primary keys when batching
Reported by: | Jacob Walls | Owned by: | Jacob Walls |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.2 |
Severity: | Release blocker | Keywords: | |
Cc: | Simon Charette, Csirmaz Bendegúz | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
The id_list
argument to in_bulk()
divides large lists into batches, but similar to #36118, it did not account for composite primary keys, leading to errors like this on SQLite:
django.db.utils.OperationalError: too many SQL variables
#36118 mentioned that other uses like this remained to be audited.
The id_list argument is tested, but the batching was not covered.
Failing test (I may adjust this in the PR to run faster by mocking a lower query param limit, but this shows the OperationalError):
-
tests/composite_pk/tests.py
diff --git a/tests/composite_pk/tests.py b/tests/composite_pk/tests.py index 91cbee0635..ba290a796f 100644
a b class CompositePKTests(TestCase): 147 147 result = Comment.objects.in_bulk([self.comment.pk]) 148 148 self.assertEqual(result, {self.comment.pk: self.comment}) 149 149 150 def test_in_bulk_batching(self): 151 num_requiring_batching = (connection.features.max_query_params // 2) + 1 152 comments = [ 153 Comment(id=i, tenant=self.tenant) 154 for i in range(2, num_requiring_batching + 1) 155 ] 156 Comment.objects.bulk_create(comments) 157 id_list = list(Comment.objects.values_list("pk", flat=True)) 158 with self.assertNumQueries(2): 159 comment_dict = Comment.objects.in_bulk(id_list=id_list) 160 self.assertQuerySetEqual(comment_dict, id_list) 161 150 162 def test_iterator(self): 151 163 """ 152 164 Test the .iterator() method of composite_pk models.
Change History (10)
comment:1 by , 3 weeks ago
Has patch: | set |
---|
comment:2 by , 3 weeks ago
Description: | modified (diff) |
---|
comment:3 by , 3 weeks ago
Cc: | added |
---|
Hello Jacob, thank you for the report and for providing a test! I'm having a bit of an issue when running the test, it seems to hang and never finishes. I've waited over 15 minutes. I have printed the values used in the tests and I have:
connection.features.max_query_params=250000 num_requiring_batching=125001
while high, these do not seem impossible. Specifically, the line that hangs is:
Comment.objects.in_bulk(id_list=id_list)
I would like to understand more about what/why this is happening before accepting. Is this failing for you on main
without your proposed fix? Or is it hanging as well?
follow-up: 6 comment:4 by , 3 weeks ago
I left a note here that I believe the slowness is simply due to the unfixed #36380 (and I added mocking in order to avoid creating such a large batch either way). The draft test finishes for me when I apply the fix for #36380 -- sorry I didn't pull these pieces together into the ticket description.
comment:5 by , 3 weeks ago
(And yes, the draft test provided with the ticket is hanging on main
for me: when CTRL-C'ing out of the hang, you can see from the trace that the issue is #36380.)
The draft test on the ticket fails on 5.2.1 if you make adjust it to run:
- provide
user=self.user
in theComment(...
instantiation - on SQLite: adjust
num_requiring_batching
to circa 999 to seeOperationalError
because below Django 6.0max_query_params
is too protective (#36143)
comment:6 by , 3 weeks ago
Cc: | added |
---|---|
Triage Stage: | Unreviewed → Accepted |
Replying to Jacob Walls:
I left a note here that I believe the slowness is simply due to the unfixed #36380 (and I added mocking in order to avoid creating such a large batch either way). The draft test finishes for me when I apply the fix for #36380 -- sorry I didn't pull these pieces together into the ticket description.
Thank you, I missed this. When running the given test with the fixes for #36380, I also get the django.db.utils.OperationalError: too many SQL variables
.
comment:7 by , 10 days ago
Triage Stage: | Accepted → Ready for checkin |
---|
PR