summaryrefslogtreecommitdiffstats
path: root/lib/private/Files
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@arthur-schiwon.de>2023-07-11 14:22:44 +0200
committerGitHub <noreply@github.com>2023-07-11 14:22:44 +0200
commit59466b3424066012ab808fa0a36c6611321fa3cb (patch)
treea37691a67f57381f28c52a528d5e09820ba989d5 /lib/private/Files
parent99ff886d5d5c2a20a204cd3bce3eba08bfdbbe7a (diff)
parent2ca8c7102bcf65d3f5ce58696d9bade504416c87 (diff)
downloadnextcloud-server-59466b3424066012ab808fa0a36c6611321fa3cb.tar.gz
nextcloud-server-59466b3424066012ab808fa0a36c6611321fa3cb.zip
Merge pull request #39233 from nextcloud/backport/39202/stable25
[stable25] use more efficient tag retrieval on DAV report request
Diffstat (limited to 'lib/private/Files')
-rw-r--r--lib/private/Files/Cache/QuerySearchHelper.php65
-rw-r--r--lib/private/Files/Cache/SearchBuilder.php17
-rw-r--r--lib/private/Files/Node/Folder.php5
-rw-r--r--lib/private/Files/Node/LazyFolder.php4
4 files changed, 59 insertions, 32 deletions
diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php
index f3401f7a9b6..df89f1261a3 100644
--- a/lib/private/Files/Cache/QuerySearchHelper.php
+++ b/lib/private/Files/Cache/QuerySearchHelper.php
@@ -38,6 +38,8 @@ use OCP\Files\Mount\IMountPoint;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchQuery;
use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\IUser;
use Psr\Log\LoggerInterface;
class QuerySearchHelper {
@@ -53,6 +55,7 @@ class QuerySearchHelper {
private $searchBuilder;
/** @var QueryOptimizer */
private $queryOptimizer;
+ private IGroupManager $groupManager;
public function __construct(
IMimeTypeLoader $mimetypeLoader,
@@ -60,7 +63,8 @@ class QuerySearchHelper {
SystemConfig $systemConfig,
LoggerInterface $logger,
SearchBuilder $searchBuilder,
- QueryOptimizer $queryOptimizer
+ QueryOptimizer $queryOptimizer,
+ IGroupManager $groupManager
) {
$this->mimetypeLoader = $mimetypeLoader;
$this->connection = $connection;
@@ -68,6 +72,7 @@ class QuerySearchHelper {
$this->logger = $logger;
$this->searchBuilder = $searchBuilder;
$this->queryOptimizer = $queryOptimizer;
+ $this->groupManager = $groupManager;
}
protected function getQueryBuilder() {
@@ -117,6 +122,29 @@ class QuerySearchHelper {
return $tags;
}
+ protected function equipQueryForSystemTags(CacheQueryBuilder $query, IUser $user): void {
+ $query->leftJoin('file', 'systemtag_object_mapping', 'systemtagmap', $query->expr()->andX(
+ $query->expr()->eq('file.fileid', $query->expr()->castColumn('systemtagmap.objectid', IQueryBuilder::PARAM_INT)),
+ $query->expr()->eq('systemtagmap.objecttype', $query->createNamedParameter('files'))
+ ));
+ $on = $query->expr()->andX($query->expr()->eq('systemtag.id', 'systemtagmap.systemtagid'));
+ if (!$this->groupManager->isAdmin($user->getUID())) {
+ $on->add($query->expr()->eq('systemtag.visibility', $query->createNamedParameter(true)));
+ }
+ $query->leftJoin('systemtagmap', 'systemtag', 'systemtag', $on);
+ }
+
+ protected function equipQueryForDavTags(CacheQueryBuilder $query, IUser $user): void {
+ $query
+ ->leftJoin('file', 'vcategory_to_object', 'tagmap', $query->expr()->eq('file.fileid', 'tagmap.objid'))
+ ->leftJoin('tagmap', 'vcategory', 'tag', $query->expr()->andX(
+ $query->expr()->eq('tagmap.type', 'tag.type'),
+ $query->expr()->eq('tagmap.categoryid', 'tag.id'),
+ $query->expr()->eq('tag.type', $query->createNamedParameter('files')),
+ $query->expr()->eq('tag.uid', $query->createNamedParameter($user->getUID()))
+ ));
+ }
+
/**
* Perform a file system search in multiple caches
*
@@ -147,27 +175,12 @@ class QuerySearchHelper {
$query = $builder->selectFileCache('file', false);
- if ($this->searchBuilder->shouldJoinTags($searchQuery->getSearchOperation())) {
- $user = $searchQuery->getUser();
- if ($user === null) {
- throw new \InvalidArgumentException("Searching by tag requires the user to be set in the query");
- }
- $query
- ->leftJoin('file', 'vcategory_to_object', 'tagmap', $builder->expr()->eq('file.fileid', 'tagmap.objid'))
- ->leftJoin('tagmap', 'vcategory', 'tag', $builder->expr()->andX(
- $builder->expr()->eq('tagmap.type', 'tag.type'),
- $builder->expr()->eq('tagmap.categoryid', 'tag.id'),
- $builder->expr()->eq('tag.type', $builder->createNamedParameter('files')),
- $builder->expr()->eq('tag.uid', $builder->createNamedParameter($user->getUID()))
- ))
- ->leftJoin('file', 'systemtag_object_mapping', 'systemtagmap', $builder->expr()->andX(
- $builder->expr()->eq('file.fileid', $builder->expr()->castColumn('systemtagmap.objectid', IQueryBuilder::PARAM_INT)),
- $builder->expr()->eq('systemtagmap.objecttype', $builder->createNamedParameter('files'))
- ))
- ->leftJoin('systemtagmap', 'systemtag', 'systemtag', $builder->expr()->andX(
- $builder->expr()->eq('systemtag.id', 'systemtagmap.systemtagid'),
- $builder->expr()->eq('systemtag.visibility', $builder->createNamedParameter(true))
- ));
+ $requestedFields = $this->searchBuilder->extractRequestedFields($searchQuery->getSearchOperation());
+ if (in_array('systemtag', $requestedFields)) {
+ $this->equipQueryForSystemTags($query, $this->requireUser($searchQuery));
+ }
+ if (in_array('tagname', $requestedFields) || in_array('favorite', $requestedFields)) {
+ $this->equipQueryForDavTags($query, $this->requireUser($searchQuery));
}
$this->applySearchConstraints($query, $searchQuery, $caches);
@@ -195,6 +208,14 @@ class QuerySearchHelper {
return $results;
}
+ protected function requireUser(ISearchQuery $searchQuery): IUser {
+ $user = $searchQuery->getUser();
+ if ($user === null) {
+ throw new \InvalidArgumentException("This search operation requires the user to be set in the query");
+ }
+ return $user;
+ }
+
/**
* @return array{0?: array<array-key, ICache>, 1?: array<array-key, IMountPoint>}
*/
diff --git a/lib/private/Files/Cache/SearchBuilder.php b/lib/private/Files/Cache/SearchBuilder.php
index 1a8c3637063..a14edc3e55e 100644
--- a/lib/private/Files/Cache/SearchBuilder.php
+++ b/lib/private/Files/Cache/SearchBuilder.php
@@ -69,20 +69,17 @@ class SearchBuilder {
}
/**
- * Whether or not the tag tables should be joined to complete the search
- *
- * @param ISearchOperator $operator
- * @return boolean
+ * @return string[]
*/
- public function shouldJoinTags(ISearchOperator $operator) {
+ public function extractRequestedFields(ISearchOperator $operator): array {
if ($operator instanceof ISearchBinaryOperator) {
- return array_reduce($operator->getArguments(), function ($shouldJoin, ISearchOperator $operator) {
- return $shouldJoin || $this->shouldJoinTags($operator);
- }, false);
+ return array_reduce($operator->getArguments(), function (array $fields, ISearchOperator $operator) {
+ return array_unique(array_merge($fields, $this->extractRequestedFields($operator)));
+ }, []);
} elseif ($operator instanceof ISearchComparison) {
- return $operator->getField() === 'tagname' || $operator->getField() === 'favorite' || $operator->getField() === 'systemtag';
+ return [$operator->getField()];
}
- return false;
+ return [];
}
/**
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index beb2ac60d55..cb97c5a6d32 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -301,6 +301,11 @@ class Folder extends Node implements \OCP\Files\Folder {
return $this->search($query);
}
+ public function searchBySystemTag(string $tagName, string $userId, int $limit = 0, int $offset = 0): array {
+ $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'systemtag', $tagName), $userId, $limit, $offset);
+ return $this->search($query);
+ }
+
/**
* @param int $id
* @return \OC\Files\Node\Node[]
diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php
index fc17ed2eb52..859ac3439be 100644
--- a/lib/private/Files/Node/LazyFolder.php
+++ b/lib/private/Files/Node/LazyFolder.php
@@ -448,6 +448,10 @@ class LazyFolder implements \OCP\Files\Folder {
return $this->__call(__FUNCTION__, func_get_args());
}
+ public function searchBySystemTag(string $tagName, string $userId, int $limit = 0, int $offset = 0): array {
+ return $this->__call(__FUNCTION__, func_get_args());
+ }
+
/**
* @inheritDoc
*/