From a2eb7a9f90d8cc786c14d7449c60d3dd00da8b9a Mon Sep 17 00:00:00 2001 From: Sujith H Date: Thu, 18 Jan 2018 20:03:05 +0530 Subject: [PATCH] Adding repair step for sub share Adding repair step for sub share. When share table due to some magic gets duplicate entries ( except the id or primary key ), then this repair step comes for rescue. Signed-off-by: Sujith H --- lib/private/Repair.php | 5 ++ lib/private/Repair/RepairSubShares.php | 106 +++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 lib/private/Repair/RepairSubShares.php diff --git a/lib/private/Repair.php b/lib/private/Repair.php index 0e876d61f077..c20c955fc61b 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -37,6 +37,7 @@ use OC\Repair\OldGroupMembershipShares; use OC\Repair\RemoveGetETagEntries; use OC\Repair\RemoveRootShares; +use OC\Repair\RepairSubShares; use OC\Repair\SharePropagation; use OC\Repair\SqliteAutoincrement; use OC\Repair\DropOldTables; @@ -157,6 +158,10 @@ public static function getRepairSteps() { \OC::$server->getConfig(), \OC::$server->getAppConfig() ), + new RepairSubShares( + \OC::$server->getConfig(), + \OC::$server->getDatabaseConnection() + ), ]; } diff --git a/lib/private/Repair/RepairSubShares.php b/lib/private/Repair/RepairSubShares.php new file mode 100644 index 000000000000..cd54dd88765a --- /dev/null +++ b/lib/private/Repair/RepairSubShares.php @@ -0,0 +1,106 @@ + + * + * @copyright Copyright (c) 2018, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Repair; + +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class RepairSubShares implements IRepairStep { + + private $connection; + + private $config; + + /** @var IQueryBuilder */ + private $getDuplicateRows; + + /** @var IQueryBuilder */ + private $deleteShareId; + + public function __construct( + IConfig $config, + IDBConnection $connection) { + $this->config = $config; + $this->connection = $connection; + } + + public function getName() { + return "Repair sub shares"; + } + + /** + * Remove duplicate rows. + * i.e, except id all columns are same for oc_share + */ + private function removeRowsWithDuplicateDataExceptId() { + /** + * Retrieves the duplicate rows with different id's + * of oc_share + */ + $builder = $this->connection->getQueryBuilder(); + $builder + ->select('id', 'parent', $builder->createFunction('count(*)')) + ->from('share') + ->where($builder->expr()->eq('share_type', '2')) + ->groupBy('parent') + ->addGroupBy('share_with') + ->having('count(*) > 1')->setMaxResults(1000); + + $this->getDuplicateRows = $builder; + + $builder = $this->connection->getQueryBuilder(); + $builder + ->delete('share') + ->where($builder->expr()->eq('id', $builder->createParameter('shareId'))); + + $this->deleteShareId = $builder; + } + + public function run(IOutput $output) { + $deletedEntries = 0; + $this->removeRowsWithDuplicateDataExceptId(); + + /** + * Going for pagination because if there are 1 million rows + * it wont be easy to scale the data + */ + do { + $results = $this->getDuplicateRows->execute(); + $rows = $results->fetchAll(); + $results->closeCursor(); + $lastResultCount = 0; + + foreach ($rows as $row) { + $deletedEntries += $this->deleteShareId->setParameter('shareId', (int) $row['id']) + ->execute(); + $lastResultCount++; + } + } while($lastResultCount > 0); + + if ($deletedEntries > 0) { + $output->info('Removed ' . $deletedEntries . ' shares where duplicate rows where found'); + } + } +} \ No newline at end of file