#28682: QuerySet.update() : return the IDs of the matched rows
-------------------------------------+-------------------------------------
     Reporter:  Дилян Палаузов       |                    Owner:  nobody
         Type:  Uncategorized        |                   Status:  new
    Component:  Database layer       |                  Version:  1.11
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Дилян Палаузов:

Old description:

> By coincidence all backends that can_return_ids_from_bulk_insert, which
> happens to be only Postgresql, can also return ids from UPDATE:
>
> UPDATE ... SET ... RETURNING id;
>
> * update QuerySet.update() to return the PKs of the updated rows
> * update the documentation of QuerySet.update(), stating the specific
> return type for PG
> * possibly rename can_return_ids_from_bulk_insert to can_return_ids or
> can_return_anything(_from_select_insert_update_delete)?

New description:

 By coincidence all backends that can_return_ids_from_bulk_insert, which
 happens to be only Postgresql, can also return ids from UPDATE:

 UPDATE ... SET ... RETURNING id;

 * update QuerySet.update() to return the PKs of the updated rows
 * update the documentation of QuerySet.update(), stating the specific
 return type for PG
 * possibly rename can_return_ids_from_bulk_insert to can_return_ids or
 can_return_anything(_from_select_insert_update_delete)?

 Like this:
 {{{
 diff --git a/django/db/models/sql/compiler.py
 b/django/db/models/sql/compiler.py
 --- a/django/db/models/sql/compiler.py
 +++ b/django/db/models/sql/compiler.py
 @@ -1230,11 +1230,11 @@ class SQLInsertCompiler(SQLCompiler):
              else:
                  result.append("VALUES (%s)" % ",
 ".join(placeholder_rows[0]))
                  params = [param_rows[0]]
 -            col = "%s.%s" % (qn(opts.db_table), qn(opts.pk.column))
              r_fmt, r_params = self.connection.ops.return_insert_id()
              # Skip empty r_fmt to allow subclasses to customize behavior
 for
              # 3rd party backends. Refs #19096.
              if r_fmt:
 +                col = "%s.%s" % (qn(opts.db_table), qn(opts.pk.column))
                  result.append(r_fmt % col)
                  params += [r_params]
              return [(" ".join(result),
 tuple(chain.from_iterable(params)))]
 @@ -1341,6 +1341,9 @@ class SQLUpdateCompiler(SQLCompiler):
          where, params = self.compile(self.query.where)
          if where:
              result.append('WHERE %s' % where)
 +        if self.connection.features.can_return_ids_from_bulk_insert:
 +            opts = self.query.get_meta()
 +            result.append("RETURNING %s.%s" % (qn(opts.db_table),
 qn(opts.pk.column)))
          return ' '.join(result), tuple(update_params + params)

      def execute_sql(self, result_type):
 @@ -1352,6 +1355,8 @@ class SQLUpdateCompiler(SQLCompiler):
          """
          cursor = super().execute_sql(result_type)
          try:
 +            if self.connection.features.can_return_ids_from_bulk_insert:
 # for Postgresql return the
 +                return
 self.connection.ops.fetch_returned_insert_ids(cursor) # PKs of the matched
 columns
              rows = cursor.rowcount if cursor else 0
              is_empty = cursor is None
          finally:
 diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
 --- a/docs/ref/models/querysets.txt
 +++ b/docs/ref/models/querysets.txt
 @@ -2241,7 +2241,8 @@ retrieves the results and then checks if any were
 returned.

  Performs an SQL update query for the specified fields, and returns
  the number of rows matched (which may not be equal to the number of rows
 -updated if some rows already have the new value).
 +updated if some rows already have the new value).  On Postgresql it
 returns
 +instead a list with the primary keys of the matched rows.

  For example, to turn comments off for all blog entries published in 2010,
  you could do this::
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28682#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/072.16bd7d86d0eba2eef667aa0caeb2c92a%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to