Change record status: 
Project: 
Introduced in branch: 
11.5.x
Introduced in version: 
11.5.0
Description: 

In the Upsert implementation, when the insert fails and the db therefore falls back to an update, we used to fall back to the minimal case of updating the record with the values passed for insert.

Now Upsert has been extended so it can update based an on expression. This can be very useful, for example, to ensure an atomic db operation to increment a counter or a score.

This happens by passing to the ::field() method an implementation of the UpsertUpdateExpression class that defines separately the behavior of the update case.

For example,


use Drupal\Core\Database\Query\UpsertUpdateExpression;

...

        $this->connection->upsert('cachetags')
          ->key(['tag'])
          ->fields([
            'tag',
            'invalidations' => new UpsertUpdateExpression('{cachetags}.[invalidations] + 1'),
          ])
          ->values([
            'tag' => $tag,
            'invalidations' => 1,
          ])
          ->execute();

would set the invalidation column value to 1 in case of an insert, or increment the column value by 1 in case of an update.

Impacts: 
Module developers