Merge pull request #22244 from nextcloud/fix/16876/better_fetch_recent
Improve recent file fetching
This commit is contained in:
commit
9809b77221
|
@ -505,4 +505,9 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
|
||||||
public function setMountOptions(array $options) {
|
public function setMountOptions(array $options) {
|
||||||
$this->mountOptions = $options;
|
$this->mountOptions = $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUnjailedPath($path) {
|
||||||
|
$this->init();
|
||||||
|
return parent::getUnjailedPath($path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
namespace OC\Files\Node;
|
namespace OC\Files\Node;
|
||||||
|
|
||||||
use OC\DB\QueryBuilder\Literal;
|
use OC\DB\QueryBuilder\Literal;
|
||||||
|
use OC\Files\Storage\Wrapper\Jail;
|
||||||
use OCA\Files_Sharing\SharedStorage;
|
use OCA\Files_Sharing\SharedStorage;
|
||||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\Files\Config\ICachedMountInfo;
|
use OCP\Files\Config\ICachedMountInfo;
|
||||||
|
@ -438,13 +439,33 @@ class Folder extends Node implements \OCP\Files\Folder {
|
||||||
$mountMap = array_combine($storageIds, $mounts);
|
$mountMap = array_combine($storageIds, $mounts);
|
||||||
$folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
|
$folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct an array of the storage id with their prefix path
|
||||||
|
* This helps us to filter in the final query
|
||||||
|
*/
|
||||||
|
$filters = array_map(function (IMountPoint $mount) {
|
||||||
|
$storage = $mount->getStorage();
|
||||||
|
|
||||||
|
$storageId = $storage->getCache()->getNumericStorageId();
|
||||||
|
$prefix = '';
|
||||||
|
|
||||||
|
if ($storage->instanceOfStorage(Jail::class)) {
|
||||||
|
$prefix = $storage->getUnJailedPath('');
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'storageId' => $storageId,
|
||||||
|
'pathPrefix' => $prefix,
|
||||||
|
];
|
||||||
|
}, $mounts);
|
||||||
|
|
||||||
// Search in batches of 500 entries
|
// Search in batches of 500 entries
|
||||||
$searchLimit = 500;
|
$searchLimit = 500;
|
||||||
$results = [];
|
$results = [];
|
||||||
$searchResultCount = 0;
|
$searchResultCount = 0;
|
||||||
$count = 0;
|
$count = 0;
|
||||||
do {
|
do {
|
||||||
$searchResult = $this->recentSearch($searchLimit, $offset, $storageIds, $folderMimetype);
|
$searchResult = $this->recentSearch($searchLimit, $offset, $folderMimetype, $filters);
|
||||||
|
|
||||||
// Exit condition if there are no more results
|
// Exit condition if there are no more results
|
||||||
if (count($searchResult) === 0) {
|
if (count($searchResult) === 0) {
|
||||||
|
@ -466,13 +487,36 @@ class Folder extends Node implements \OCP\Files\Folder {
|
||||||
return array_slice($results, 0, $limit);
|
return array_slice($results, 0, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function recentSearch($limit, $offset, $storageIds, $folderMimetype) {
|
private function recentSearch($limit, $offset, $folderMimetype, $filters) {
|
||||||
$builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
|
$dbconn = \OC::$server->getDatabaseConnection();
|
||||||
|
$builder = $dbconn->getQueryBuilder();
|
||||||
$query = $builder
|
$query = $builder
|
||||||
->select('f.*')
|
->select('f.*')
|
||||||
->from('filecache', 'f')
|
->from('filecache', 'f');
|
||||||
->andWhere($builder->expr()->in('f.storage', $builder->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY)))
|
|
||||||
->andWhere($builder->expr()->orX(
|
/*
|
||||||
|
* Here is where we construct the filtering.
|
||||||
|
* Note that this is expensive filtering as it is a lot of like queries.
|
||||||
|
* However the alternative is we do this filtering and parsing later in php with the risk of looping endlessly
|
||||||
|
*/
|
||||||
|
$storageFilters = $builder->expr()->orX();
|
||||||
|
foreach ($filters as $filter) {
|
||||||
|
$storageFilter = $builder->expr()->andX(
|
||||||
|
$builder->expr()->eq('f.storage', $builder->createNamedParameter($filter['storageId']))
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($filter['pathPrefix'] !== '') {
|
||||||
|
$storageFilter->add(
|
||||||
|
$builder->expr()->like('f.path', $builder->createNamedParameter($dbconn->escapeLikeParameter($filter['pathPrefix']) . '/%'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$storageFilters->add($storageFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->andWhere($storageFilters);
|
||||||
|
|
||||||
|
$query->andWhere($builder->expr()->orX(
|
||||||
// handle non empty folders separate
|
// handle non empty folders separate
|
||||||
$builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
|
$builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
|
||||||
$builder->expr()->eq('f.size', new Literal(0))
|
$builder->expr()->eq('f.size', new Literal(0))
|
||||||
|
@ -482,6 +526,7 @@ class Folder extends Node implements \OCP\Files\Folder {
|
||||||
->orderBy('f.mtime', 'DESC')
|
->orderBy('f.mtime', 'DESC')
|
||||||
->setMaxResults($limit)
|
->setMaxResults($limit)
|
||||||
->setFirstResult($offset);
|
->setFirstResult($offset);
|
||||||
|
|
||||||
return $query->execute()->fetchAll();
|
return $query->execute()->fetchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue