Skip to content

Commit 116c8ca

Browse files
committed
fix: make mount point name compatible with sharding by switching it to the list of root ids
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent 4b612c3 commit 116c8ca

1 file changed

Lines changed: 54 additions & 3 deletions

File tree

‎lib/private/Files/Cache/QuerySearchHelper.php‎

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010
use OC\Files\Cache\Wrapper\CacheJail;
1111
use OC\Files\Search\QueryOptimizer\QueryOptimizer;
1212
use OC\Files\Search\SearchBinaryOperator;
13+
use OC\Files\Search\SearchComparison;
14+
use OC\Files\Search\SearchQuery;
1315
use OCP\DB\QueryBuilder\IQueryBuilder;
1416
use OCP\Files\Cache\ICache;
1517
use OCP\Files\Cache\ICacheEntry;
1618
use OCP\Files\IMimeTypeLoader;
1719
use OCP\Files\IRootFolder;
1820
use OCP\Files\Mount\IMountPoint;
1921
use OCP\Files\Search\ISearchBinaryOperator;
22+
use OCP\Files\Search\ISearchComparison;
23+
use OCP\Files\Search\ISearchOperator;
2024
use OCP\Files\Search\ISearchQuery;
2125
use OCP\FilesMetadata\IFilesMetadataManager;
2226
use OCP\FilesMetadata\IMetadataQuery;
@@ -95,7 +99,7 @@ public function findUsedTagsInCaches(ISearchQuery $searchQuery, array $caches):
9599
protected function equipQueryForSystemTags(CacheQueryBuilder $query, IUser $user): void {
96100
$query->leftJoin('file', 'systemtag_object_mapping', 'systemtagmap', $query->expr()->andX(
97101
$query->expr()->eq('file.fileid', $query->expr()->castColumn('systemtagmap.objectid', IQueryBuilder::PARAM_INT)),
98-
$query->expr()->eq('systemtagmap.objecttype', $query->createNamedParameter('files'))
102+
$query->expr()->eq('systemtagmap.objecttype', $query->createNamedParameter('files')),
99103
));
100104
$on = $query->expr()->andX($query->expr()->eq('systemtag.id', 'systemtagmap.systemtagid'));
101105
if (!$this->groupManager->isAdmin($user->getUID())) {
@@ -110,15 +114,15 @@ protected function equipQueryForDavTags(CacheQueryBuilder $query, IUser $user):
110114
->leftJoin('tagmap', 'vcategory', 'tag', $query->expr()->andX(
111115
$query->expr()->eq('tagmap.categoryid', 'tag.id'),
112116
$query->expr()->eq('tag.type', $query->createNamedParameter('files')),
113-
$query->expr()->eq('tag.uid', $query->createNamedParameter($user->getUID()))
117+
$query->expr()->eq('tag.uid', $query->createNamedParameter($user->getUID())),
114118
));
115119
}
116120

117121
protected function equipQueryForMounts(CacheQueryBuilder $query, IUser $user): void {
118122
$query
119123
->leftJoin('file', 'mounts', 'm', $query->expr()->andX(
120124
$query->expr()->eq('m.root_id', 'file.fileid'),
121-
$query->expr()->eq('m.user_id', $query->createNamedParameter($user->getUID()))
125+
$query->expr()->eq('m.user_id', $query->createNamedParameter($user->getUID())),
122126
));
123127
}
124128

@@ -152,6 +156,8 @@ public function searchInCaches(ISearchQuery $searchQuery, array $caches): array
152156
// while the resulting rows don't have a way to tell what storage they came from (multiple storages/caches can share storage_id)
153157
// we can just ask every cache if the row belongs to them and give them the cache to do any post processing on the result.
154158

159+
$searchQuery = $this->preProcessQuery($searchQuery);
160+
155161
$builder = $this->getQueryBuilder();
156162

157163
$requestedFields = array_merge(
@@ -253,4 +259,49 @@ public function getCachesAndMountPointsForSearch(IRootFolder $root, string $path
253259

254260
return [$caches, $mountByMountPoint];
255261
}
262+
263+
private function preProcessQuery(ISearchQuery $searchQuery): ISearchQuery {
264+
// when sharding is enabled, we can't join on the mounts table
265+
// so instead we need to fetch the matching mount root ids and filter on those
266+
if ($this->connection->getShardDefinition('filecache') !== null) {
267+
$operation = $this->replaceMountNameWithRootIds($searchQuery->getSearchOperation());
268+
return new SearchQuery(
269+
$operation,
270+
$searchQuery->getLimit(),
271+
$searchQuery->getOffset(),
272+
$searchQuery->getOrder(),
273+
$searchQuery->getUser(),
274+
$searchQuery->limitToHome(),
275+
$searchQuery->getSelectFields(),
276+
);
277+
} else {
278+
return $searchQuery;
279+
}
280+
}
281+
282+
private function replaceMountNameWithRootIds(ISearchOperator $searchOperator): ISearchOperator {
283+
if ($searchOperator instanceof ISearchBinaryOperator) {
284+
return new SearchBinaryOperator(
285+
$searchOperator->getType(),
286+
array_map($this->replaceMountNameWithRootIds(...), $searchOperator->getArguments())
287+
);
288+
} elseif ($searchOperator instanceof ISearchComparison && $searchOperator->getField() === 'mount_point_name') {
289+
if (!in_array($searchOperator->getType(), [
290+
ISearchComparison::COMPARE_LIKE,
291+
ISearchComparison::COMPARE_EQUAL,
292+
ISearchComparison::COMPARE_IN,
293+
], true)) {
294+
throw new \InvalidArgumentException('Filtering mount name with ' . $searchOperator->getType() . ' is not supported');
295+
}
296+
297+
$query = $this->connection->getQueryBuilder();
298+
$query->select('root_id')
299+
->from('mounts', 'm')
300+
->where($this->searchBuilder->searchOperatorToDBExpr($query, $searchOperator));
301+
$rootIds = $query->executeQuery()->fetchAll(\PDO::FETCH_COLUMN);
302+
return new SearchComparison(ISearchComparison::COMPARE_IN, 'fileid', $rootIds);
303+
} else {
304+
return $searchOperator;
305+
}
306+
}
256307
}

0 commit comments

Comments
 (0)