nextcloud / nextcloud/server

QBMapper::insertOrUpdate can lead to NotNullConstraintViolationException

Open
#21,705 9 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

1. to develop technical debt
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

Code in question:

https://github.com/nextcloud/server/blob/d78449c01cf1cc608eca7a4d6ae675f1bc3e8aeb/lib/public/AppFramework/Db/QBMapper.php#L150
and
https://github.com/nextcloud/server/blob/d78449c01cf1cc608eca7a4d6ae675f1bc3e8aeb/lib/public/AppFramework/Db/QBMapper.php#L111

Problem:
  1. Have a DB Scheme that does not allow null for some fields:
    e.g: [userId, key, value], where userId and key are not allowed to be null.
  2. Have this line in the DB: ['uid123', 'key1', 'value2']
  3. $entity = $mapper->findByUid('uid123')
  4. $entity->setValue('new-value-456')
  5. $mapper->insertOrUpdate($entity)
  6. 💥

Reason:

  • QBMapper::insertOrUpdate tries to insert it. If it throws a UniqueConstraintViolationException it performs an update instead.
  • QBMapper::insert does not insert all fields, but only the updated fields.
  • In our example, it would only insert value: new-value-456, because that's the only field we altered, although userId and key are set in the entity, leading to a NotNullConstraintViolationException.
Possible Solutions:
  1. Instead of using the updated fields, use array_keys($entity->getFieldTypes())
    https://github.com/nextcloud/server/blob/d78449c01cf1cc608eca7a4d6ae675f1bc3e8aeb/lib/public/AppFramework/Db/QBMapper.php#L114
  • will create bigger insert statements, possibly inserting lots of null values.
  • insert is widely used, might do 💥 very easily.
  1. Deprecate insertOrUpdate, it's barely used anyway (only once in the server right now)
    https://github.com/nextcloud/server/search?q=insertOrUpdate&unscoped_q=insertOrUpdate

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read lib/public/AppFramework/Db/QBMapper.php around the linked insertOrUpdate and insert lines, then trace how updated fields are selected. Reproduce the findByUid, setValue, and insertOrUpdate scenario against a schema with non-null userId and key fields. Done means the operation no longer raises NotNullConstraintViolationException while its insert-or-update behavior remains defined.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.