From f404122aa8e2678696d83831fd6303aaac30e3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Fri, 3 Mar 2023 10:35:50 +0100 Subject: [PATCH] Add chunking in SystemTagObjectMapper::getTagIdsForObjects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids crashing on Oracle with more than 1000 objects Signed-off-by: Côme Chilliet --- .../SystemTag/SystemTagObjectMapper.php | 16 +++++++------- .../SystemTag/SystemTagObjectMapperTest.php | 21 ++++++++++++++----- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php index 5a09a1754f27a..b61a81a1fa701 100644 --- a/lib/private/SystemTag/SystemTagObjectMapper.php +++ b/lib/private/SystemTag/SystemTagObjectMapper.php @@ -77,23 +77,25 @@ public function getTagIdsForObjects($objIds, string $objectType): array { ->from(self::RELATION_TABLE) ->where($query->expr()->in('objectid', $query->createParameter('objectids'))) ->andWhere($query->expr()->eq('objecttype', $query->createParameter('objecttype'))) - ->setParameter('objectids', $objIds, IQueryBuilder::PARAM_STR_ARRAY) ->setParameter('objecttype', $objectType) ->addOrderBy('objectid', 'ASC') ->addOrderBy('systemtagid', 'ASC'); - + $chunks = array_chunk($objIds, 900, false); $mapping = []; foreach ($objIds as $objId) { $mapping[$objId] = []; } + foreach ($chunks as $chunk) { + $query->setParameter('objectids', $chunk, IQueryBuilder::PARAM_STR_ARRAY); + $result = $query->executeQuery(); + while ($row = $result->fetch()) { + $objectId = $row['objectid']; + $mapping[$objectId][] = $row['systemtagid']; + } - $result = $query->execute(); - while ($row = $result->fetch()) { - $objectId = $row['objectid']; - $mapping[$objectId][] = $row['systemtagid']; + $result->closeCursor(); } - $result->closeCursor(); return $mapping; } diff --git a/tests/lib/SystemTag/SystemTagObjectMapperTest.php b/tests/lib/SystemTag/SystemTagObjectMapperTest.php index a5158bbee68d1..bf6d65863f4f3 100644 --- a/tests/lib/SystemTag/SystemTagObjectMapperTest.php +++ b/tests/lib/SystemTag/SystemTagObjectMapperTest.php @@ -142,6 +142,17 @@ public function testGetTagIdsForNoObjects() { $this->assertEquals([], $tagIdMapping); } + public function testGetTagIdsForALotOfObjects() { + $ids = range(1, 10500); + $tagIdMapping = $this->tagMapper->getTagIdsForObjects( + $ids, + 'testtype' + ); + + $this->assertEquals(10500, count($tagIdMapping)); + $this->assertEquals([$this->tag1->getId(), $this->tag2->getId()], $tagIdMapping[1]); + } + public function testGetObjectsForTags() { $objectIds = $this->tagMapper->getObjectIdsForTags( [$this->tag1->getId(), $this->tag2->getId(), $this->tag3->getId()], @@ -166,7 +177,7 @@ public function testGetObjectsForTagsLimit() { ], $objectIds); } - + public function testGetObjectsForTagsLimitWithMultipleTags() { $this->expectException(\InvalidArgumentException::class); @@ -190,7 +201,7 @@ public function testGetObjectsForTagsLimitOffset() { ], $objectIds); } - + public function testGetObjectsForNonExistingTag() { $this->expectException(\OCP\SystemTag\TagNotFoundException::class); @@ -228,7 +239,7 @@ public function testReAssignUnassignTags() { $this->assertTrue(true, 'No error when reassigning/unassigning'); } - + public function testAssignNonExistingTags() { $this->expectException(\OCP\SystemTag\TagNotFoundException::class); @@ -255,7 +266,7 @@ public function testAssignNonExistingTagInArray() { ], $tagIdMapping, 'None of the tags got assigned'); } - + public function testUnassignNonExistingTags() { $this->expectException(\OCP\SystemTag\TagNotFoundException::class); @@ -386,7 +397,7 @@ public function testHaveTagAtLeastOneMatch() { ); } - + public function testHaveTagNonExisting() { $this->expectException(\OCP\SystemTag\TagNotFoundException::class);