Follow up of #3586760: Use composite key Upsert queries in core.

Problem/Motivation

There are probably more opportunities to use Upsert with composite key capability in core.

In the Upsert implementation, when the insert fails and the db therefore falls back to an update, we are currently falling back to the minimal case of updating the record with the values passed for insert. However UPSERT can do much more; it can update based an expression. This can be very useful for, for example, ensure an atomic db operation to increment a counter or a score.

Proposed resolution

Extend Upsert to allow specifying column specific expressions for the update case.

Leverage on that to convert all remaining uses of Merge in core, with the exception of StringDatabaseStorage, TaxonomyHooks, Drupal\Core\KeyValueStore\DatabaseStorage.

BONUS: now cache tag invalidations require a single db roundtrip and are atomic.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Issue fork drupal-3604286

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mondrake created an issue. See original summary.

mondrake’s picture

Title: Use more composite key Upsert queries in core » Upsert - Allow to customize the behavior of the update after the insert and use more Upsert queries in core
Issue summary: View changes
mondrake’s picture

Title: Upsert - Allow to customize the behavior of the update after the insert and use more Upsert queries in core » Upsert - Allow to customize the behavior of the update when the insert fails and use more Upsert queries in core
Status: Active » Needs review

Byproduct: now cache tag invalidations require a single db roundtrip and are atomic.

mondrake’s picture

There's somethiing definitely broken with StringDatabaseStorage, if we try to add a unique index on all the columns of the table but lid in the update path, we get duplicate key errors.

So reverting the changes to that part (which would be questionable anyway due to adding a unique key), and will have to be addressed separately.

mondrake’s picture

Issue summary: View changes
mondrake’s picture

Green on all dbs.

mondrake’s picture

Assigned: Unassigned » mondrake
Status: Needs review » Needs work

Working on introducing a value object that defines the insert and the update cases in a single point.

mondrake’s picture

Status: Needs work » Needs review
mondrake’s picture

Assigned: mondrake » Unassigned
daffie’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record

The PR looks good!
Just a couple of remarks.
We also need a change record.

mondrake’s picture

Status: Needs work » Needs review
mondrake’s picture

Issue summary: View changes

Reverted controversial changes for now - we can readd later or in follow-ups if needed.

mondrake’s picture

Issue tags: -Needs change record

Added draft CR.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

It all looks good to me.
The IS and the CR are also in order.
All the code changes look good to me.
For all changes there is testing added.
For me it is RTBC.

mondrake’s picture

Issue summary: View changes
mondrake’s picture

mondrake’s picture

Assigned: Unassigned » mondrake
Status: Reviewed & tested by the community » Needs work

There’s a flaw here. Will explain later.

mondrake’s picture

Assigned: mondrake » Unassigned
Status: Needs work » Needs review

The problem was conceptual - the definition of the update expression was being done as part of specifying the values to be upserted, but we might have multiple set of values in a single upsert operation. In that case, there would be no unique place where to indicate the update expression, that is unique within the upsert. In the latest commit, now that is being done as part of specifying the columns (=fields), that is a one time operation per each upsert call.

mondrake’s picture

Updated CR

daffie’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.
Back to RTBC.

mondrake’s picture

Status: Reviewed & tested by the community » Postponed
Related issues: +#3611653: Upsert fails after upgrade from 11.3 to 11.4
mondrake’s picture

mondrake’s picture

Status: Postponed » Reviewed & tested by the community

Rebased. I had to remove the test that was checking that there was a failure if no columns to be updated were specified, because #3611653: Upsert fails after upgrade from 11.3 to 11.4 actually now supports the 'ignore' case for duplicated keys with no update. I am bold on re-RTBC but a +1 would help I suppose.

mondrake’s picture

Assigned: Unassigned » mondrake
Status: Reviewed & tested by the community » Needs work
Related issues: +#3586688: Add support for generated columns to the DB Schema API

The MR here adds an Expression class that would fit nicely with #3586688: Add support for generated columns to the DB Schema API, too. But then the class should better be located in the Drupal\Core\Database namespace instead of the Drupal\Core\Database\Query one. On it.

mondrake’s picture

Assigned: mondrake » Unassigned
Status: Needs work » Needs review

Done #25.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.
Back to RTBC.

amateescu’s picture

Status: Reviewed & tested by the community » Needs work

Reviewed the MR and left some code suggestions. Setting back to NW for the bindParam()/bindValue() change, which is an actual bug.

mondrake’s picture

Status: Needs work » Needs review

Thanks for the review and suggestions. I applied them all.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

All improvements of @amateescu have been applied.
Back to RTBC.

  • amateescu committed 7bdc1c89 on 11.x
    task: #3604286 Upsert - Allow to customize the behavior of the update...
amateescu’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 047e314b510 to main and 7bdc1c89b0f to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • amateescu committed 047e314b on main
    task: #3604286 Upsert - Allow to customize the behavior of the update...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.