-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
refactor: Migrate away from \OCP\IDBConnection::insertIfNotExist #57124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
d9b3fde to
d161459
Compare
Signed-off-by: provokateurin <kate@provokateurin.de>
Signed-off-by: provokateurin <kate@provokateurin.de>
Signed-off-by: provokateurin <kate@provokateurin.de>
d161459 to
7eb9092
Compare
| $this->db->insertIfNotExist('*PREFIX*dav_shares', [ | ||
| 'principaluri' => 'principal:unknown', | ||
| 'type' => 'calendar', | ||
| 'access' => 2, | ||
| 'resourceid' => 666, | ||
| ]); | ||
| $this->db->insertIfNotExist('*PREFIX*dav_shares', [ | ||
| 'principaluri' => 'principals/remote-users/foobar', | ||
| 'type' => 'calendar', | ||
| 'access' => 2, | ||
| 'resourceid' => 666, | ||
| ]); | ||
| $qb = $this->db->getQueryBuilder(); | ||
| $qb->insert('dav_shares'); | ||
|
|
||
| foreach (['principal:unknown', 'principals/remote-users/foobar'] as $principaluri) { | ||
| $qb->values([ | ||
| 'principaluri' => $qb->createNamedParameter($principaluri), | ||
| 'type' => $qb->createNamedParameter('calendar'), | ||
| 'access' => $qb->createNamedParameter(2, IQueryBuilder::PARAM_INT), | ||
| 'resourceid' => $qb->createNamedParameter(666, IQueryBuilder::PARAM_INT), | ||
| ]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous insertIfNotExists compared all input fields, while the unique index is create unique index dav_shares_index on oc_dav_shares (principaluri, resourceid, type, publicuri);. This seems to result in different numbers of rows, but only on sharding for some reason. I can't fully judge this, but I think the tests are incorrect in some way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't really wrap my head around the unique index vs the semantics of the insertIfNotExists. But the index definitely is not helping getting an atomic operation here.
How does the logic change with sharding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the index definitely is not helping getting an atomic operation here.
How so? Before it was a SELECT + INSERT which was not atomic at all, leading to the duplicated oc_mounts issue. Now its UNIQUE INDEX + INSERT and this definitely is atomic.
How does the logic change with sharding?
This is what confuses me the most, it's not failing without sharding. I feel like this could be a bug in the sharding code? CC @icewind1991
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The index will only ensure that the (principaluri, resourceid, type, null) is unique. It doesn't cover the access column. So if you have an existing row (principaluri, resourceid, type, anything but null) the insert still happens without a unique constraint violation.
The old insertIfNotExist was not guaranteed to be atomic, but in the case of no concurrent modifications of the table (like in the sequentially executed phpunit tests) it still prevented duplicates with identical (principaluri, resourceid, type, access).
But I think we are on the same page anyway :)
The test outcome makes no sense. I also think that the sharding somehow doesn't send the deletions in the command to the same db instance as the select for the insertion.
A unique index must be used to actually guarantee no duplicates, as this method is not even transaction safe (with READ_COMMITTED)