From 59144ace90cdb366a142cc55e31fa7adec654c4c Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Tue, 7 Apr 2026 12:31:56 +0200 Subject: [PATCH 1/2] fix(previews): fix chunking for querybuilder Signed-off-by: Anna Larch --- .../Preview/Storage/LocalPreviewStorage.php | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/lib/private/Preview/Storage/LocalPreviewStorage.php b/lib/private/Preview/Storage/LocalPreviewStorage.php index c5221a2b93d4a..a64fdfe295fa5 100644 --- a/lib/private/Preview/Storage/LocalPreviewStorage.php +++ b/lib/private/Preview/Storage/LocalPreviewStorage.php @@ -310,20 +310,18 @@ private function fetchFilecacheByFileIds(array $fileIds): array { } $result = []; - $qb = $this->connection->getTypedQueryBuilder(); - $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype') - ->from('filecache'); foreach (array_chunk($fileIds, 1000) as $chunk) { - $qb->andWhere( - $qb->expr()->in('fileid', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)) - ); - } - $rows = $qb->runAcrossAllShards() - ->executeQuery(); - while ($row = $rows->fetchAssociative()) { - $result[(int)$row['fileid']] = $row; + $qb = $this->connection->getTypedQueryBuilder(); + $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype') + ->from('filecache') + ->where($qb->expr()->in('fileid', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); + $rows = $qb->runAcrossAllShards() + ->executeQuery(); + while ($row = $rows->fetchAssociative()) { + $result[(int)$row['fileid']] = $row; + } + $rows->closeCursor(); } - $rows->closeCursor(); return $result; } @@ -338,20 +336,18 @@ private function fetchFilecacheByPathHashes(array $pathHashes): array { } $result = []; - $qb = $this->connection->getTypedQueryBuilder(); - $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype', 'parent', 'path_hash') - ->from('filecache'); foreach (array_chunk($pathHashes, 1000) as $chunk) { - $qb->andWhere( - $qb->expr()->in('path_hash', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)) - ); - } - $rows = $qb->runAcrossAllShards() - ->executeQuery(); - while ($row = $rows->fetchAssociative()) { - $result[$row['path_hash']] = $row; + $qb = $this->connection->getTypedQueryBuilder(); + $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype', 'parent', 'path_hash') + ->from('filecache') + ->where($qb->expr()->in('path_hash', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))); + $rows = $qb->runAcrossAllShards() + ->executeQuery(); + while ($row = $rows->fetchAssociative()) { + $result[$row['path_hash']] = $row; + } + $rows->closeCursor(); } - $rows->closeCursor(); return $result; } From 0681ced2031869d260ba88fc42b8a1c6998b50e2 Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Mon, 4 May 2026 18:59:09 +0200 Subject: [PATCH 2/2] fix(previews): use createParameter/setParameter to reuse query in chunk loop AI-Assisted-By: claude-sonnet-4-6 Signed-off-by: Anna Larch AI-Assisted-By: Claude Sonnet 4.6 --- .../Preview/Storage/LocalPreviewStorage.php | 26 ++++++++++--------- .../Storage/LocalPreviewStorageTest.php | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/private/Preview/Storage/LocalPreviewStorage.php b/lib/private/Preview/Storage/LocalPreviewStorage.php index a64fdfe295fa5..13e6a7145167b 100644 --- a/lib/private/Preview/Storage/LocalPreviewStorage.php +++ b/lib/private/Preview/Storage/LocalPreviewStorage.php @@ -310,13 +310,14 @@ private function fetchFilecacheByFileIds(array $fileIds): array { } $result = []; + $qb = $this->connection->getTypedQueryBuilder(); + $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype') + ->from('filecache') + ->where($qb->expr()->in('fileid', $qb->createParameter('fileIds'))) + ->runAcrossAllShards(); foreach (array_chunk($fileIds, 1000) as $chunk) { - $qb = $this->connection->getTypedQueryBuilder(); - $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype') - ->from('filecache') - ->where($qb->expr()->in('fileid', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); - $rows = $qb->runAcrossAllShards() - ->executeQuery(); + $qb->setParameter('fileIds', $chunk, IQueryBuilder::PARAM_INT_ARRAY); + $rows = $qb->executeQuery(); while ($row = $rows->fetchAssociative()) { $result[(int)$row['fileid']] = $row; } @@ -336,13 +337,14 @@ private function fetchFilecacheByPathHashes(array $pathHashes): array { } $result = []; + $qb = $this->connection->getTypedQueryBuilder(); + $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype', 'parent', 'path_hash') + ->from('filecache') + ->where($qb->expr()->in('path_hash', $qb->createParameter('pathHashes'))) + ->runAcrossAllShards(); foreach (array_chunk($pathHashes, 1000) as $chunk) { - $qb = $this->connection->getTypedQueryBuilder(); - $qb->selectColumns('fileid', 'storage', 'etag', 'mimetype', 'parent', 'path_hash') - ->from('filecache') - ->where($qb->expr()->in('path_hash', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))); - $rows = $qb->runAcrossAllShards() - ->executeQuery(); + $qb->setParameter('pathHashes', $chunk, IQueryBuilder::PARAM_STR_ARRAY); + $rows = $qb->executeQuery(); while ($row = $rows->fetchAssociative()) { $result[$row['path_hash']] = $row; } diff --git a/tests/lib/Preview/Storage/LocalPreviewStorageTest.php b/tests/lib/Preview/Storage/LocalPreviewStorageTest.php index dbc3cea5342a3..14e6419a9d538 100644 --- a/tests/lib/Preview/Storage/LocalPreviewStorageTest.php +++ b/tests/lib/Preview/Storage/LocalPreviewStorageTest.php @@ -129,6 +129,7 @@ private function buildQueryBuilderMock(array $rows): IQueryBuilder&MockObject { $qbMock = $this->createMock(ITypedQueryBuilder::class); $qbMock->method('selectColumns')->willReturnSelf(); $qbMock->method('from')->willReturnSelf(); + $qbMock->method('where')->willReturnSelf(); $qbMock->method('andWhere')->willReturnSelf(); $qbMock->method('runAcrossAllShards')->willReturnSelf(); $qbMock->method('executeQuery')->willReturn($resultMock);