Merge pull request #60960 from nextcloud/carl/querybuilder-magic-number
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, main, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, guests_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, main, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / changes (push) Waiting to run
Psalm static code analysis / static-code-analysis (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-security (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-ocp (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-ncu (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-strict (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis-summary (push) Blocked by required conditions

refactor: Use new IQueryBuilder::MAX_IN_PARAMETERS
This commit is contained in:
Benjamin Gaussorgues 2026-06-10 23:09:30 +02:00 committed by GitHub
commit 2b7415ef4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 40 additions and 31 deletions

View file

@ -3237,7 +3237,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$deleteQuery = $this->db->getQueryBuilder();
$deleteQuery->delete('schedulingobjects')
->where($deleteQuery->expr()->in('id', $deleteQuery->createParameter('ids'), IQueryBuilder::PARAM_INT_ARRAY));
foreach (array_chunk($ids, 1000) as $chunk) {
foreach (array_chunk($ids, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$deleteQuery->setParameter('ids', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
$numDeleted += $deleteQuery->executeStatement();
}
@ -3772,7 +3772,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
$this->atomic(function () use ($subscriptionId, $calendarObjectIds, $calendarObjectUris): void {
foreach (array_chunk($calendarObjectIds, 1000) as $chunk) {
foreach (array_chunk($calendarObjectIds, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$query = $this->db->getQueryBuilder();
$query->delete($this->dbObjectPropertiesTable)
->where($query->expr()->eq('calendarid', $query->createNamedParameter($subscriptionId)))
@ -3788,7 +3788,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
->executeStatement();
}
foreach (array_chunk($calendarObjectUris, 1000) as $chunk) {
foreach (array_chunk($calendarObjectUris, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$query = $this->db->getQueryBuilder();
$query->delete('calendarchanges')
->where($query->expr()->eq('calendarid', $query->createNamedParameter($subscriptionId)))

View file

@ -1268,7 +1268,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
->from($this->dbCardsTable, 'c')
->where($query->expr()->in('c.id', $query->createParameter('matches')));
foreach (array_chunk($matches, 1000) as $matchesChunk) {
foreach (array_chunk($matches, IQueryBuilder::MAX_IN_PARAMETERS) as $matchesChunk) {
$query->setParameter('matches', $matchesChunk, IQueryBuilder::PARAM_INT_ARRAY);
$result = $query->executeQuery();
$cardResults[] = $result->fetchAllAssociative();

View file

@ -497,7 +497,7 @@ class CustomPropertiesBackend implements BackendInterface {
if (!empty($requestedProperties)) {
// request only a subset
$qb->andWhere($qb->expr()->in('propertyname', $qb->createParameter('requestedProperties')));
$chunks = array_chunk($requestedProperties, 1000);
$chunks = array_chunk($requestedProperties, IQueryBuilder::MAX_IN_PARAMETERS);
foreach ($chunks as $chunk) {
$qb->setParameter('requestedProperties', $chunk, IQueryBuilder::PARAM_STR_ARRAY);
$result = $qb->executeQuery();

View file

@ -35,7 +35,6 @@ use Psr\Log\LoggerInterface;
*/
class SharesReminderJob extends TimedJob {
private const SECONDS_BEFORE_REMINDER = 24 * 60 * 60;
private const CHUNK_SIZE = 1000;
private int $folderMimeTypeId;
public function __construct(
@ -131,7 +130,7 @@ class SharesReminderJob extends TimedJob {
$qb->expr()->isNull('f.fileid')
)
)
->setMaxResults(SharesReminderJob::CHUNK_SIZE);
->setMaxResults(IQueryBuilder::MAX_IN_PARAMETERS);
$shares = $qb->executeQuery()->fetchAllAssociative();
return array_map(fn ($share): array => [
@ -178,7 +177,7 @@ class SharesReminderJob extends TimedJob {
'share_type' => (int)$share['share_type'],
'file_source' => (int)$share['file_source'],
], $shares);
return $this->filterSharesWithEmptyFolders($shares, self::CHUNK_SIZE);
return $this->filterSharesWithEmptyFolders($shares, IQueryBuilder::MAX_IN_PARAMETERS);
}
/**
@ -193,7 +192,7 @@ class SharesReminderJob extends TimedJob {
->where($query->expr()->eq('size', $query->createNamedParameter(0), IQueryBuilder::PARAM_INT_ARRAY))
->andWhere($query->expr()->eq('mimetype', $query->createNamedParameter($this->folderMimeTypeId, IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->in('fileid', $query->createParameter('fileids')));
$chunks = array_chunk($shares, SharesReminderJob::CHUNK_SIZE);
$chunks = array_chunk($shares, IQueryBuilder::MAX_IN_PARAMETERS);
$results = [];
foreach ($chunks as $chunk) {
$chunkFileIds = array_map(fn ($share): int => $share['file_source'], $chunk);

View file

@ -64,7 +64,7 @@ class GroupMembershipMapper extends QBMapper {
$query->delete($this->getTableName())
->where($query->expr()->in('groupid', $query->createParameter('groupids')));
foreach (array_chunk($removedGroups, 1000) as $removedGroupsChunk) {
foreach (array_chunk($removedGroups, IQueryBuilder::MAX_IN_PARAMETERS) as $removedGroupsChunk) {
$query->setParameter('groupids', $removedGroupsChunk, IQueryBuilder::PARAM_STR_ARRAY);
$query->executeStatement();
}

View file

@ -707,7 +707,7 @@ class Manager implements ICommentsManager {
}
$unreadComments = array_fill_keys($objectIds, 0);
foreach (array_chunk($objectIds, 1000) as $chunk) {
foreach (array_chunk($objectIds, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$query->setParameter('ids', $chunk, IQueryBuilder::PARAM_STR_ARRAY);
$result = $query->executeQuery();

View file

@ -85,7 +85,7 @@ class CrossShardMoveHelper {
->from($table)
->where($query->expr()->in($primaryColumn, $query->createParameter('keys')));
$chunks = array_chunk($primaryKeys, 1000);
$chunks = array_chunk($primaryKeys, IQueryBuilder::MAX_IN_PARAMETERS);
$results = [];
foreach ($chunks as $chunk) {
@ -152,7 +152,7 @@ class CrossShardMoveHelper {
$query = $connection->getQueryBuilder();
$query->delete($table)
->where($query->expr()->in($primaryColumn, $query->createParameter('keys')));
$chunks = array_chunk($primaryKeys, 1000);
$chunks = array_chunk($primaryKeys, IQueryBuilder::MAX_IN_PARAMETERS);
foreach ($chunks as $chunk) {
$query->setParameter('keys', $chunk, IQueryBuilder::PARAM_INT_ARRAY);

View file

@ -623,7 +623,7 @@ class Cache implements ICache {
->where($query->expr()->in('fileid', $query->createParameter('childIds')))
->hintShardKey('storage', $this->getNumericStorageId());
foreach (array_chunk($childIds, 1000) as $childIdChunk) {
foreach (array_chunk($childIds, IQueryBuilder::MAX_IN_PARAMETERS) as $childIdChunk) {
$query->setParameter('childIds', $childIdChunk, IQueryBuilder::PARAM_INT_ARRAY);
$query->executeStatement();
}
@ -649,13 +649,13 @@ class Cache implements ICache {
// Sorting before chunking allows the db to find the entries close to each
// other in the index
sort($parentIds, SORT_NUMERIC);
foreach (array_chunk($parentIds, 1000) as $parentIdChunk) {
foreach (array_chunk($parentIds, IQueryBuilder::MAX_IN_PARAMETERS) as $parentIdChunk) {
$query->setParameter('parentIds', $parentIdChunk, IQueryBuilder::PARAM_INT_ARRAY);
$query->executeStatement();
}
$cacheEntryRemovedEvents = [];
foreach (array_chunk(array_combine($deletedIds, $deletedPaths), 1000) as $chunk) {
foreach (array_chunk(array_combine($deletedIds, $deletedPaths), IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
/** @var array<int, string> $chunk */
foreach ($chunk as $fileId => $filePath) {
$cacheEntryRemovedEvents[] = new CacheEntryRemovedEvent(
@ -764,7 +764,7 @@ class Cache implements ICache {
$childIds = $this->getChildIds($sourceStorageId, $sourcePath);
$childChunks = array_chunk($childIds, 1000);
$childChunks = array_chunk($childIds, IQueryBuilder::MAX_IN_PARAMETERS);
$query = $this->getQueryBuilder();

View file

@ -206,7 +206,7 @@ class Propagator implements IPropagator {
// queries as a faster lookup than the path_hash
$hashes = array_map(static fn (array $a): string => $a['hash'], $this->batch);
foreach (array_chunk($hashes, 1000) as $hashesChunk) {
foreach (array_chunk($hashes, IQueryBuilder::MAX_IN_PARAMETERS) as $hashesChunk) {
$query = $this->connection->getQueryBuilder();
$result = $query->select('fileid', 'path', 'path_hash', 'size')
->from('filecache')

View file

@ -45,7 +45,7 @@ class StorageGlobal {
->from('storages')
->where($builder->expr()->in('id', $builder->createParameter('ids'), IQueryBuilder::PARAM_STR_ARRAY));
foreach (array_chunk($storageIds, 1000) as $chunk) {
foreach (array_chunk($storageIds, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$query->setParameter('ids', $chunk, IQueryBuilder::PARAM_STR_ARRAY);
$result = $query->executeQuery();

View file

@ -9,6 +9,7 @@ namespace OC\Files\Search\QueryOptimizer;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
@ -22,9 +23,9 @@ class SplitLargeIn extends ReplacingOptimizerStep {
if (
$operator instanceof ISearchComparison
&& $operator->getType() === ISearchComparison::COMPARE_IN
&& count($operator->getValue()) > 1000
&& count($operator->getValue()) > IQueryBuilder::MAX_IN_PARAMETERS
) {
$chunks = array_chunk($operator->getValue(), 1000);
$chunks = array_chunk($operator->getValue(), IQueryBuilder::MAX_IN_PARAMETERS);
$chunkComparisons = array_map(function (array $values) use ($operator) {
return new SearchComparison(ISearchComparison::COMPARE_IN, $operator->getField(), $values, $operator->getExtra());
}, $chunks);

View file

@ -28,6 +28,7 @@ use OCA\Files_Sharing\ISharedMountPoint;
use OCA\Files_Sharing\SharedMount;
use OCP\App\IAppManager;
use OCP\Constants;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IAuthoritativeMountProvider;
@ -605,7 +606,7 @@ class SetupManager implements ISetupManager {
);
$rootsMetadata = [];
foreach (array_chunk($rootIds, 1000) as $chunk) {
foreach (array_chunk($rootIds, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
foreach ($this->fileAccess->getByFileIds($chunk) as $id => $fileMetadata) {
$rootsMetadata[$id] = $fileMetadata;
}

View file

@ -186,7 +186,7 @@ class IndexRequestService {
* @throws DbException
*/
public function dropIndexForFiles(array $fileIds, string $key = ''): void {
$chunks = array_chunk($fileIds, 1000);
$chunks = array_chunk($fileIds, IQueryBuilder::MAX_IN_PARAMETERS);
foreach ($chunks as $chunk) {
$qb = $this->dbConnection->getQueryBuilder();

View file

@ -150,7 +150,7 @@ class MetadataRequestService {
* @throws Exception
*/
public function dropMetadataForFiles(int $storage, array $fileIds): void {
$chunks = array_chunk($fileIds, 1000);
$chunks = array_chunk($fileIds, IQueryBuilder::MAX_IN_PARAMETERS);
foreach ($chunks as $chunk) {
$qb = $this->dbConnection->getQueryBuilder();

View file

@ -342,7 +342,7 @@ class Database extends ABackend implements
$qb->select('gid', 'displayname')
->from('groups')
->where($qb->expr()->in('gid', $qb->createParameter('ids')));
foreach (array_chunk($notFoundGids, 1000) as $chunk) {
foreach (array_chunk($notFoundGids, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$qb->setParameter('ids', $chunk, IQueryBuilder::PARAM_STR_ARRAY);
$result = $qb->executeQuery();
while ($row = $result->fetch()) {
@ -553,7 +553,7 @@ class Database extends ABackend implements
}
}
foreach (array_chunk($notFoundGids, 1000) as $chunk) {
foreach (array_chunk($notFoundGids, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$query = $this->dbConn->getQueryBuilder();
$query->select('gid', 'displayname')
->from('groups')

View file

@ -315,7 +315,7 @@ class LocalPreviewStorage implements IPreviewStorage {
->from('filecache')
->where($qb->expr()->in('fileid', $qb->createParameter('fileIds')))
->runAcrossAllShards();
foreach (array_chunk($fileIds, 1000) as $chunk) {
foreach (array_chunk($fileIds, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$qb->setParameter('fileIds', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
$rows = $qb->executeQuery();
while ($row = $rows->fetchAssociative()) {
@ -342,7 +342,7 @@ class LocalPreviewStorage implements IPreviewStorage {
->from('filecache')
->where($qb->expr()->in('path_hash', $qb->createParameter('pathHashes')))
->runAcrossAllShards();
foreach (array_chunk($pathHashes, 1000) as $chunk) {
foreach (array_chunk($pathHashes, IQueryBuilder::MAX_IN_PARAMETERS) as $chunk) {
$qb->setParameter('pathHashes', $chunk, IQueryBuilder::PARAM_STR_ARRAY);
$rows = $qb->executeQuery();
while ($row = $rows->fetchAssociative()) {

View file

@ -51,7 +51,7 @@ class RemoveBrokenProperties implements IRepairStep {
$qb = $this->db->getQueryBuilder();
$qb->delete('properties')
->where($qb->expr()->in('id', $qb->createParameter('ids'), IQueryBuilder::PARAM_STR_ARRAY));
foreach (array_chunk($brokenIds, 1000) as $chunkIds) {
foreach (array_chunk($brokenIds, IQueryBuilder::MAX_IN_PARAMETERS) as $chunkIds) {
$qb->setParameter('ids', $chunkIds, IQueryBuilder::PARAM_STR_ARRAY);
$qb->executeStatement();
}

View file

@ -685,7 +685,7 @@ class DefaultShareProvider implements
$shares = [];
$chunks = array_chunk($childMountRootIds, 1000);
$chunks = array_chunk($childMountRootIds, IQueryBuilder::MAX_IN_PARAMETERS);
// Force the request to be run when there is 0 mount.
if (count($chunks) === 0) {

View file

@ -128,7 +128,7 @@ class TagManager implements ITagManager, IEventListener {
$qb1 = $qb1->delete('vcategory')
->where($qb1->expr()->in('uid', $qb1->createParameter('chunk')));
foreach (array_chunk($tagsIds, 1000) as $tagChunk) {
foreach (array_chunk($tagsIds, IQueryBuilder::MAX_IN_PARAMETERS) as $tagChunk) {
$qb->setParameter('chunk', $tagChunk, IQueryBuilder::PARAM_INT_ARRAY);
$qb1->setParameter('chunk', $tagChunk, IQueryBuilder::PARAM_INT_ARRAY);
try {

View file

@ -120,6 +120,14 @@ interface IQueryBuilder {
*/
public const MAX_ROW_DELETION = 100000;
/**
* @since 35.0.0 Indicates how many parameters can be passed to a IN query
* with Oracle database server.
*
* Mostly useful as magic value to give to array_chunk
*/
public const MAX_IN_PARAMETERS = 1000;
/**
* Enable/disable automatic prefixing of table names with the oc_ prefix
*