From 157e9e110fc9a20f238339c447fcd09495a07d3f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Tue, 13 Oct 2026 11:14:58 +0200 Subject: [PATCH] perf(sharing): skip resolving group shares when there are none Setting up the mount of a received share looks up group shares for the path, and then queries the user specific group share entries to apply them, even when no group share was found. The result can only change the group shares found, so skip the query when there are none. This saves a query on every access to a received share for users without group shares for the path. Assisted-by: ClaudeCode:claude-opus-5-5 Signed-off-by: Carl Schwan --- lib/private/Share20/DefaultShareProvider.php | 5 ++++- tests/lib/Share20/DefaultShareProviderTest.php | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index de0dfcfa67402..59328d27fe906 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -1071,6 +1071,9 @@ private function _getSharedWith( /* * Resolve all group shares to user specific shares */ + if ($shares2 === []) { + return []; + } $shares = $this->resolveGroupShares($shares2, $userId, $path, $forChildren); } else { throw new BackendError('Invalid backend'); @@ -1178,7 +1181,7 @@ private function createShare($data): IShare { /** * Update the data from group shares with any per-user modifications * - * @param array $shareMap shares indexed by share id + * @param non-empty-array $shareMap shares indexed by share id * @param $userId * @return Share[] The updates shares if no update is found for a share return the original */ diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php index 89b5ea544b746..fbb6294a51819 100644 --- a/tests/lib/Share20/DefaultShareProviderTest.php +++ b/tests/lib/Share20/DefaultShareProviderTest.php @@ -35,6 +35,7 @@ use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager as IShareManager; use OCP\Share\IShare; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; @@ -1056,6 +1057,19 @@ public function testGetSharedWithUser($storageStringId, $fileName1, $fileName2): $this->assertEquals(IShare::TYPE_USER, $share->getShareType()); } + #[TestWith([[], 0])] + #[TestWith([['group1', 'group2'], 1])] + public function testGetSharedWithGroupWithoutGroupShares(array $groups, int $expectedQueries): void { + $this->groupManager->method('getUserGroupIds')->willReturn($groups); + $connection = $this->dbConn->getInner(); + + $queriesBefore = $connection->getStats()['executed']; + $shares = $this->provider->getSharedWithByPath('sharedWith', IShare::TYPE_GROUP, '/sharedWith/files/target', false, -1, 0); + + $this->assertSame([], $shares); + $this->assertSame($expectedQueries, $connection->getStats()['executed'] - $queriesBefore); + } + #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')] public function testGetSharedWithGroup($storageStringId, $fileName1, $fileName2): void { $storageId = $this->createTestStorageEntry($storageStringId);