1717use OCP \Files \IRootFolder ;
1818use OCP \Files \Mount \IMountPoint ;
1919use OCP \Files \Search \ISearchBinaryOperator ;
20+ use OCP \Files \Search \ISearchComparison ;
21+ use OCP \Files \Search \ISearchOperator ;
2022use OCP \Files \Search \ISearchQuery ;
2123use OCP \FilesMetadata \IFilesMetadataManager ;
2224use OCP \FilesMetadata \IMetadataQuery ;
@@ -98,7 +100,7 @@ public function findUsedTagsInCaches(ISearchQuery $searchQuery, array $caches):
98100 protected function equipQueryForSystemTags (CacheQueryBuilder $ query , IUser $ user ): void {
99101 $ query ->leftJoin ('file ' , 'systemtag_object_mapping ' , 'systemtagmap ' , $ query ->expr ()->andX (
100102 $ query ->expr ()->eq ('file.fileid ' , $ query ->expr ()->castColumn ('systemtagmap.objectid ' , IQueryBuilder::PARAM_INT )),
101- $ query ->expr ()->eq ('systemtagmap.objecttype ' , $ query ->createNamedParameter ('files ' ))
103+ $ query ->expr ()->eq ('systemtagmap.objecttype ' , $ query ->createNamedParameter ('files ' )),
102104 ));
103105 $ on = $ query ->expr ()->andX ($ query ->expr ()->eq ('systemtag.id ' , 'systemtagmap.systemtagid ' ));
104106 if (!$ this ->groupManager ->isAdmin ($ user ->getUID ())) {
@@ -113,7 +115,7 @@ protected function equipQueryForDavTags(CacheQueryBuilder $query, IUser $user):
113115 ->leftJoin ('tagmap ' , 'vcategory ' , 'tag ' , $ query ->expr ()->andX (
114116 $ query ->expr ()->eq ('tagmap.categoryid ' , 'tag.id ' ),
115117 $ query ->expr ()->eq ('tag.type ' , $ query ->createNamedParameter ('files ' )),
116- $ query ->expr ()->eq ('tag.uid ' , $ query ->createNamedParameter ($ user ->getUID ()))
118+ $ query ->expr ()->eq ('tag.uid ' , $ query ->createNamedParameter ($ user ->getUID ())),
117119 ));
118120 }
119121
@@ -148,6 +150,8 @@ public function searchInCaches(ISearchQuery $searchQuery, array $caches): array
148150 // while the resulting rows don't have a way to tell what storage they came from (multiple storages/caches can share storage_id)
149151 // 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.
150152
153+ $ searchQuery = $ this ->preProcessQuery ($ searchQuery );
154+
151155 $ builder = $ this ->getQueryBuilder ();
152156
153157 $ requestedFields = array_merge (
@@ -249,4 +253,49 @@ public function getCachesAndMountPointsForSearch(IRootFolder $root, string $path
249253
250254 return [$ caches , $ mountByMountPoint ];
251255 }
256+
257+ private function preProcessQuery (ISearchQuery $ searchQuery ): ISearchQuery {
258+ // when sharding is enabled, we can't join on the mounts table
259+ // so instead we need to fetch the matching mount root ids and filter on those
260+ if ($ this ->connection ->getShardDefinition ('filecache ' ) !== null ) {
261+ $ operation = $ this ->replaceMountNameWithRootIds ($ searchQuery ->getSearchOperation ());
262+ return new SearchQuery (
263+ $ operation ,
264+ $ searchQuery ->getLimit (),
265+ $ searchQuery ->getOffset (),
266+ $ searchQuery ->getOrder (),
267+ $ searchQuery ->getUser (),
268+ $ searchQuery ->limitToHome (),
269+ $ searchQuery ->getSelectFields (),
270+ );
271+ } else {
272+ return $ searchQuery ;
273+ }
274+ }
275+
276+ private function replaceMountNameWithRootIds (ISearchOperator $ searchOperator ): ISearchOperator {
277+ if ($ searchOperator instanceof ISearchBinaryOperator) {
278+ return new SearchBinaryOperator (
279+ $ searchOperator ->getType (),
280+ array_map ($ this ->replaceMountNameWithRootIds (...), $ searchOperator ->getArguments ())
281+ );
282+ } elseif ($ searchOperator instanceof ISearchComparison && $ searchOperator ->getField () === 'mount_point_name ' ) {
283+ if (!in_array ($ searchOperator ->getType (), [
284+ ISearchComparison::COMPARE_LIKE ,
285+ ISearchComparison::COMPARE_EQUAL ,
286+ ISearchComparison::COMPARE_IN ,
287+ ], true )) {
288+ throw new \InvalidArgumentException ('Filtering mount name with ' . $ searchOperator ->getType () . ' is not supported ' );
289+ }
290+
291+ $ query = $ this ->connection ->getQueryBuilder ();
292+ $ query ->select ('root_id ' )
293+ ->from ('mounts ' , 'm ' )
294+ ->where ($ this ->searchBuilder ->searchOperatorToDBExpr ($ query , $ searchOperator ));
295+ $ rootIds = $ query ->executeQuery ()->fetchAll (\PDO ::FETCH_COLUMN );
296+ return new SearchComparison (ISearchComparison::COMPARE_IN , 'fileid ' , $ rootIds );
297+ } else {
298+ return $ searchOperator ;
299+ }
300+ }
252301}
0 commit comments