]> source.dussan.org Git - nextcloud-server.git/commitdiff
Fix UniqueConstraintViolationException while insert into oc_filecache
authorMorris Jobke <hey@morrisjobke.de>
Mon, 12 Nov 2018 12:43:46 +0000 (13:43 +0100)
committerMorris Jobke <hey@morrisjobke.de>
Tue, 13 Nov 2018 12:59:15 +0000 (13:59 +0100)
* fixes #6160 by not being prone to the race condition in insertIfNotExists
* fixes #12228 by not using a query that can result in a deadlock
* replaces the insertIfNotExists call with an insert which is wrapped into a try-catch block

Signed-off-by: Morris Jobke <hey@morrisjobke.de>
lib/private/Files/Cache/Cache.php

index 007bccf0a54bb7c54e46c18ea73e4c2677642a50..1cb11c70a4061927ad3ded1a25424faf573c04e3 100644 (file)
@@ -37,6 +37,7 @@
 
 namespace OC\Files\Cache;
 
+use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use Doctrine\DBAL\Driver\Statement;
 use OCP\Files\Cache\ICache;
@@ -238,6 +239,8 @@ class Cache implements ICache {
         *
         * @return int file id
         * @throws \RuntimeException
+        *
+        * @suppress SqlInjectionChecker
         */
        public function insert($file, array $data) {
                // normalize file
@@ -268,12 +271,20 @@ class Cache implements ICache {
                        return trim($item, "`");
                }, $queryParts);
                $values = array_combine($queryParts, $params);
-               if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [
-                       'storage',
-                       'path_hash',
-               ])
-               ) {
-                       return (int)$this->connection->lastInsertId('*PREFIX*filecache');
+
+               try {
+                       $builder = $this->connection->getQueryBuilder();
+                       $builder->insert('filecache');
+
+                       foreach ($values as $column => $value) {
+                               $builder->setValue($column, $builder->createNamedParameter($value));
+                       }
+
+                       if ($builder->execute()) {
+                               return (int)$this->connection->lastInsertId('*PREFIX*filecache');
+                       }
+               } catch(UniqueConstraintViolationException $e) {
+                       // entry exists already
                }
 
                // The file was created in the mean time
@@ -281,7 +292,7 @@ class Cache implements ICache {
                        $this->update($id, $data);
                        return $id;
                } else {
-                       throw new \RuntimeException('File entry could not be inserted with insertIfNotExist() but could also not be selected with getId() in order to perform an update. Please try again.');
+                       throw new \RuntimeException('File entry could not be inserted but could also not be selected with getId() in order to perform an update. Please try again.');
                }
        }