Code

Opened 3 years ago

Last modified 11 months ago

#16891 new New feature

QuerySet.delete() should return number of rows matched

Reported by: estebistec Owned by: estebistec
Component: Database layer (models, ORM) Version: 1.3
Severity: Normal Keywords:
Cc: sergeykolosov Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by carljm)

Splitting this off from ticket #16549...

Deep in the bowels of django.db the rows modified value from update and delete queries is ignored and discarded. For reasons discussed on ticket 16549, it would sometimes be useful to have access to that value.

Objective of this bug is to passively return rows-modified up through the call-stack and, ultimately, hopefully from each of:

  • Model.save()
  • Model.delete()
  • QuerySet.update()
  • QuerySet.delete()

with consideration for transaction control/mgmt.

Update from comment thread: queryset update already returns rows-matched (and this can't be changed to rows-changed without breaking other things). So it is only deletes that need this change.

Attachments (1)

delete_counts.patch (1.1 KB) - added by estebistec 2 years ago.
Patch to changes so far from git clone

Download all attachments as: .zip

Change History (17)

comment:1 Changed 3 years ago by estebistec

  • Needs documentation unset
  • Needs tests unset
  • Owner changed from nobody to estebistec
  • Patch needs improvement unset

Claiming to work on.

comment:2 Changed 3 years ago by carljm

  • Component changed from Uncategorized to Database layer (models, ORM)
  • Triage Stage changed from Unreviewed to Accepted
  • Type changed from Uncategorized to New feature

comment:3 Changed 3 years ago by estebistec

Finally got around to these simple changes:

If the core devs approve of these changes I can get to work on creating the proper patch for SVN and add doc changes.

comment:4 Changed 3 years ago by akaariai

An idea for the save() patch: return UPDATED, INSERTED, or None instead of 1/0. You could still do if obj.save(): (matches both UPDATED and INSERTED) but if need be, you could see if the object was indeed updated or inserted. The value would be the "outermost" value for multitable inherited models.

I wonder if it would be a good idea to return the amount of deletions per object type when deleting? I see at least three choices:

  • Just a dict model_class -> delete count, for example in your test case this would be {R:1, S:2, T:2}
  • Tuple total_objects_deleted, abovementioned dict: Example: (5, {R:1, S:2, T:2})
  • Tuple amount_of_outer_objs, abovementioned dict: Example: (1, {R:1, S:2, T:2})

To me it seems these could be useful, especially the #2 format. This information can be gotten nearly for free. The inconvenience here is that you can't do if obj.delete(): as (0, {}) isn't False. Maybe this could be postponed for later inclusion with kwarg with_counts=True or something. Or maybe there is just no use case for this.

comment:5 Changed 3 years ago by estebistec

In case anybody is paying more attention here than on django-dev, I made an update to roll the changes back to just the internal query classes for now:

Changed 2 years ago by estebistec

Patch to changes so far from git clone

comment:6 follow-up: Changed 2 years ago by estebistec

  • Has patch set

I haven't gotten much feedback on this ticket, but what I've gotten so far has convinced me to back off of any changes to the base Model API. UpdateQuery already returned rowcounts, which means that only DeleteQuery needed updating. So, the patch is pretty tiny as you can see.

comment:7 Changed 2 years ago by estebistec

  • Summary changed from Delete/update should return number of rows modified to [patch] Delete/update should return number of rows modified

Updating summary

comment:8 Changed 2 years ago by aaugustin

#17435 was a duplicate.

comment:9 in reply to: ↑ 6 Changed 2 years ago by sergeykolosov

  • Cc sergeykolosov added

Replying to estebistec:

I haven't gotten much feedback on this ticket, but what I've gotten so far has convinced me to back off of any changes to the base Model API. UpdateQuery already returned rowcounts, which means that only DeleteQuery needed updating. So, the patch is pretty tiny as you can see.

Since QuerySet.update returns not the number of rows affected, but the number of rows matched (as I’ve described it in #17435), I believe the UpdateQuery still needs to be patched.

comment:10 Changed 2 years ago by estebistec

Yeah, if there are no objections to rolling #17435 into this bug, I'll go back in and add QuerySet.update to the patch.

comment:11 follow-up: Changed 2 years ago by kmtracey

No, I don't think update() can be switched to start returning the actually-modified row count rather than matched row count. See #17435 for why, the fix for that one is to clarify the doc.

comment:12 in reply to: ↑ 11 Changed 2 years ago by estebistec

Replying to kmtracey:

No, I don't think update() can be switched to start returning the actually-modified row count rather than matched row count. See #17435 for why, the fix for that one is to clarify the doc.

So I need to take a closer look here too and see if the delete() counts can mirror update() in that way.

comment:13 Changed 2 years ago by anonymous

  • Patch needs improvement set

comment:14 Changed 2 years ago by carljm

  • Description modified (diff)
  • Summary changed from [patch] Delete/update should return number of rows modified to [patch] queryset delete should return number of rows matched

comment:15 Changed 2 years ago by estebistec

  • Patch needs improvement unset

The ambiguity discussed in #17435 doesn't apply to deletes. The number of rows matched and affected can't differ, as a match always leads to a delete. So I think the existing patch is fine in this respect.

Are there any other improvements needed in this patch? It doesn't look like the objects at this level are generally tested in the Django test-suite. On the one hand, more tests are always good. On the other, the delete queries aren't part of Django's published object model (for me, they're an implementation detail change along the way to ticket #16549).

comment:16 Changed 11 months ago by timo

  • Needs documentation set
  • Needs tests set
  • Patch needs improvement set
  • Summary changed from [patch] queryset delete should return number of rows matched to QuerySet.delete() should return number of rows matched

I marked #12086 as a duplicate. The attached patch doesn't make QuerySet.delete() return the number of deleted objects like I would expect (based on what's suggested by the ticket summary). This also needs tests and docs.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as new
The owner will be changed from estebistec to anonymous. Next status will be 'assigned'
as The resolution will be set. Next status will be 'closed'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.