Skip to content

Commit 48551eb

Browse files
committed
fix(core): handle parameter limits in files metadata deletion
Refactor dropMetadataForFiles and dropIndexForFiles to chunk by 500 and wrap in database transactions to avoid query parameter limit errors on Oracle and PostgreSQL. Assisted-by: Antigravity:Gemini-3.5-Flash Signed-off-by: Edmond <edmnd@users.noreply.github.com>
1 parent d49f90b commit 48551eb

3 files changed

Lines changed: 96 additions & 17 deletions

File tree

lib/private/FilesMetadata/Service/IndexRequestService.php

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,26 @@ public function dropIndex(int $fileId, string $key = ''): void {
186186
* @throws DbException
187187
*/
188188
public function dropIndexForFiles(array $fileIds, string $key = ''): void {
189-
$chunks = array_chunk($fileIds, IQueryBuilder::MAX_IN_PARAMETERS);
189+
$chunks = array_chunk($fileIds, 500);
190190

191-
foreach ($chunks as $chunk) {
192-
$qb = $this->dbConnection->getQueryBuilder();
193-
$expr = $qb->expr();
194-
$qb->delete(self::TABLE_METADATA_INDEX)
195-
->where($expr->in('file_id', $qb->createNamedParameter($fileIds, IQueryBuilder::PARAM_INT_ARRAY)));
191+
$this->dbConnection->beginTransaction();
192+
try {
193+
foreach ($chunks as $chunk) {
194+
$qb = $this->dbConnection->getQueryBuilder();
195+
$expr = $qb->expr();
196+
$qb->delete(self::TABLE_METADATA_INDEX)
197+
->where($expr->in('file_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
196198

197-
if ($key !== '') {
198-
$qb->andWhere($expr->eq('meta_key', $qb->createNamedParameter($key)));
199-
}
199+
if ($key !== '') {
200+
$qb->andWhere($expr->eq('meta_key', $qb->createNamedParameter($key)));
201+
}
200202

201-
$qb->executeStatement();
203+
$qb->executeStatement();
204+
}
205+
$this->dbConnection->commit();
206+
} catch (DbException $e) {
207+
$this->dbConnection->rollBack();
208+
throw $e;
202209
}
203210
}
204211
}

lib/private/FilesMetadata/Service/MetadataRequestService.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,21 @@ public function dropMetadata(int $fileId): void {
150150
* @throws Exception
151151
*/
152152
public function dropMetadataForFiles(int $storage, array $fileIds): void {
153-
$chunks = array_chunk($fileIds, IQueryBuilder::MAX_IN_PARAMETERS);
153+
$chunks = array_chunk($fileIds, 500);
154154

155-
foreach ($chunks as $chunk) {
156-
$qb = $this->dbConnection->getQueryBuilder();
157-
$qb->delete(self::TABLE_METADATA)
158-
->where($qb->expr()->in('file_id', $qb->createNamedParameter($fileIds, IQueryBuilder::PARAM_INT_ARRAY)))
159-
->hintShardKey('storage', $storage);
160-
$qb->executeStatement();
155+
$this->dbConnection->beginTransaction();
156+
try {
157+
foreach ($chunks as $chunk) {
158+
$qb = $this->dbConnection->getQueryBuilder();
159+
$qb->delete(self::TABLE_METADATA)
160+
->where($qb->expr()->in('file_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)))
161+
->hintShardKey('storage', $storage);
162+
$qb->executeStatement();
163+
}
164+
$this->dbConnection->commit();
165+
} catch (Exception $e) {
166+
$this->dbConnection->rollBack();
167+
throw $e;
161168
}
162169
}
163170

tests/lib/FilesMetadata/FilesMetadataManagerTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,69 @@ public function testRefreshMetadata(): void {
9494
$this->assertEquals($file->getId(), $retrieved->getFileId());
9595
$this->assertEquals('yes', $retrieved->getString('istest'));
9696
}
97+
98+
public function testDropMetadataForFilesChunking(): void {
99+
$connection = $this->createMock(IDBConnection::class);
100+
$qb = $this->createMock(\OCP\DB\QueryBuilder\IQueryBuilder::class);
101+
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
102+
103+
$connection->expects($this->once())->method('beginTransaction');
104+
$connection->expects($this->once())->method('commit');
105+
$connection->expects($this->never())->method('rollBack');
106+
107+
$connection->method('getQueryBuilder')->willReturn($qb);
108+
$qb->method('expr')->willReturn($expr);
109+
$qb->method('delete')->willReturnSelf();
110+
$qb->method('where')->willReturnSelf();
111+
$qb->method('hintShardKey')->willReturnSelf();
112+
113+
// We chunk 2000 items into 500. So we expect 4 queries.
114+
$fileIds = range(1, 2000);
115+
116+
$qb->expects($this->exactly(4))
117+
->method('createNamedParameter')
118+
->with($this->callback(function (array $chunk) {
119+
return count($chunk) === 500;
120+
}), \OCP\DB\QueryBuilder\IQueryBuilder::PARAM_INT_ARRAY)
121+
->willReturn(':param');
122+
123+
$qb->expects($this->exactly(4))
124+
->method('executeStatement')
125+
->willReturn(1);
126+
127+
$service = new MetadataRequestService($connection, $this->logger);
128+
$service->dropMetadataForFiles(123, $fileIds);
129+
}
130+
131+
public function testDropIndexForFilesChunking(): void {
132+
$connection = $this->createMock(IDBConnection::class);
133+
$qb = $this->createMock(\OCP\DB\QueryBuilder\IQueryBuilder::class);
134+
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
135+
136+
$connection->expects($this->once())->method('beginTransaction');
137+
$connection->expects($this->once())->method('commit');
138+
$connection->expects($this->never())->method('rollBack');
139+
140+
$connection->method('getQueryBuilder')->willReturn($qb);
141+
$qb->method('expr')->willReturn($expr);
142+
$qb->method('delete')->willReturnSelf();
143+
$qb->method('where')->willReturnSelf();
144+
145+
$fileIds = range(1, 2000);
146+
147+
$qb->expects($this->exactly(4))
148+
->method('createNamedParameter')
149+
->with($this->callback(function (array $chunk) {
150+
return count($chunk) === 500;
151+
}), \OCP\DB\QueryBuilder\IQueryBuilder::PARAM_INT_ARRAY)
152+
->willReturn(':param');
153+
154+
$qb->expects($this->exactly(4))
155+
->method('executeStatement')
156+
->willReturn(1);
157+
158+
$service = new IndexRequestService($connection, $this->logger);
159+
$service->dropIndexForFiles($fileIds);
160+
}
97161
}
162+

0 commit comments

Comments
 (0)