1010use OC \Files \Cache \Wrapper \CacheJail ;
1111use OC \Files \Search \QueryOptimizer \QueryOptimizer ;
1212use OC \Files \Search \SearchBinaryOperator ;
13+ use OC \Files \Search \SearchComparison ;
14+ use OC \Files \Search \SearchQuery ;
1315use OCP \DB \QueryBuilder \IQueryBuilder ;
1416use OCP \Files \Cache \ICache ;
1517use OCP \Files \Cache \ICacheEntry ;
1618use OCP \Files \IMimeTypeLoader ;
1719use OCP \Files \IRootFolder ;
1820use OCP \Files \Mount \IMountPoint ;
1921use OCP \Files \Search \ISearchBinaryOperator ;
22+ use OCP \Files \Search \ISearchComparison ;
23+ use OCP \Files \Search \ISearchOperator ;
2024use OCP \Files \Search \ISearchQuery ;
2125use OCP \FilesMetadata \IFilesMetadataManager ;
2226use 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