From 9552b2f44f2c30f63f8af6357a39e07a0bd3ff47 Mon Sep 17 00:00:00 2001 From: grnd-alt Date: Mon, 14 Sep 2026 16:18:53 +0200 Subject: [PATCH 1/2] fix(db): chunk queries for shared boards Signed-off-by: grnd-alt --- lib/Db/BoardMapper.php | 68 ++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/lib/Db/BoardMapper.php b/lib/Db/BoardMapper.php index 8ebabc83a..ddf305df3 100644 --- a/lib/Db/BoardMapper.php +++ b/lib/Db/BoardMapper.php @@ -9,7 +9,6 @@ use OCA\Deck\Service\CirclesService; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Db\QBMapper; use OCP\Cache\CappedMemoryCache; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Federation\ICloudIdManager; @@ -18,8 +17,8 @@ use OCP\IUserManager; use Psr\Log\LoggerInterface; -/** @template-extends QBMapper */ -class BoardMapper extends QBMapper implements IPermissionMapper { +/** @template-extends DeckMapper */ +class BoardMapper extends DeckMapper implements IPermissionMapper { /** @var CappedMemoryCache */ private CappedMemoryCache $userBoardCache; /** @var CappedMemoryCache */ @@ -93,16 +92,20 @@ public function findBoardIds(string $userId): array { }, $result->fetchAll(\PDO::FETCH_COLUMN)); $result->closeCursor(); + // Shared to the user $qb = $this->db->getQueryBuilder(); $qb->selectDistinct('b.id') ->from($this->getTableName(), 'b') - ->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id')); - - // Shared to the user - $qb->where($qb->expr()->andX( - $qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_USER, IQueryBuilder::PARAM_INT)), - $qb->expr()->eq('acl.participant', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)), - )); + ->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id')) + ->where($qb->expr()->andX( + $qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_USER, IQueryBuilder::PARAM_INT)), + $qb->expr()->eq('acl.participant', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)), + )); + $result = $qb->executeQuery(); + $sharedBoards = array_map(function (string $id) { + return (int)$id; + }, $result->fetchAll(\PDO::FETCH_COLUMN)); + $result->closeCursor(); // Shared to user groups of the user $user = $this->userManager->get($userId); @@ -111,26 +114,45 @@ public function findBoardIds(string $userId): array { $groupIds = $this->groupManager->getUserGroupIds($user); } if ($groupIds !== null && count($groupIds) !== 0) { - $qb->orWhere($qb->expr()->andX( - $qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_GROUP, IQueryBuilder::PARAM_INT)), - $qb->expr()->in('acl.participant', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)), - )); + $sharedBoards = array_merge($sharedBoards, iterator_to_array($this->chunkQuery($groupIds, function (array $groupIdsChunk): array { + $qb = $this->db->getQueryBuilder(); + $qb->selectDistinct('b.id') + ->from($this->getTableName(), 'b') + ->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id')) + ->where($qb->expr()->andX( + $qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_GROUP, IQueryBuilder::PARAM_INT)), + $qb->expr()->in('acl.participant', $qb->createNamedParameter($groupIdsChunk, IQueryBuilder::PARAM_STR_ARRAY)), + )); + $result = $qb->executeQuery(); + $boardIds = array_map(function (string $id) { + return (int)$id; + }, $result->fetchAll(\PDO::FETCH_COLUMN)); + $result->closeCursor(); + return $boardIds; + }), false)); } // Shared to circles of the user $circles = $this->circlesService->getUserCircles($userId); if (count($circles) !== 0) { - $qb->orWhere($qb->expr()->andX( - $qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)), - $qb->expr()->in('acl.participant', $qb->createNamedParameter($circles, IQueryBuilder::PARAM_STR_ARRAY)), - )); + $sharedBoards = array_merge($sharedBoards, iterator_to_array($this->chunkQuery($circles, function (array $circlesChunk): array { + $qb = $this->db->getQueryBuilder(); + $qb->selectDistinct('b.id') + ->from($this->getTableName(), 'b') + ->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id')) + ->where($qb->expr()->andX( + $qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)), + $qb->expr()->in('acl.participant', $qb->createNamedParameter($circlesChunk, IQueryBuilder::PARAM_STR_ARRAY)), + )); + $result = $qb->executeQuery(); + $boardIds = array_map(function (string $id) { + return (int)$id; + }, $result->fetchAll(\PDO::FETCH_COLUMN)); + $result->closeCursor(); + return $boardIds; + }), false)); } - $result = $qb->executeQuery(); - $sharedBoards = array_map(function (string $id) { - return (int)$id; - }, $result->fetchAll(\PDO::FETCH_COLUMN)); - $result->closeCursor(); return array_unique(array_merge($ownerBoards, $sharedBoards)); } /** From e9ab942ab1bf1ece1faf1aa8e165905bc6ff4c8a Mon Sep 17 00:00:00 2001 From: grnd-alt Date: Mon, 14 Sep 2026 16:46:37 +0200 Subject: [PATCH 2/2] fix(ci): use ->get instead of ->query Signed-off-by: grnd-alt --- tests/integration/app/AppTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/app/AppTest.php b/tests/integration/app/AppTest.php index 7e062dd08..34b83f4fc 100644 --- a/tests/integration/app/AppTest.php +++ b/tests/integration/app/AppTest.php @@ -40,7 +40,7 @@ public function setUp(): void { } public function testAppInstalled() { - $appManager = $this->container->query('OCP\App\IAppManager'); + $appManager = $this->container->get('OCP\App\IAppManager'); $this->assertTrue($appManager->isInstalled('deck')); } }