use searchoperation for storage filter instead of db expression

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2021-05-05 18:09:53 +02:00
parent d2e5f084c8
commit c3277095c7
No known key found for this signature in database
GPG Key ID: 42B69D8A64526EFB
8 changed files with 62 additions and 46 deletions

View File

@ -31,9 +31,13 @@ namespace OCA\Files_Sharing;
use OC\Files\Cache\FailedCache;
use OC\Files\Cache\Wrapper\CacheJail;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
use OC\Files\Storage\Wrapper\Jail;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\StorageNotAvailableException;
/**
@ -183,18 +187,19 @@ class Cache extends CacheJail {
// Not a valid action for Shared Cache
}
public function getQueryFilterForStorage(IQueryBuilder $builder) {
public function getQueryFilterForStorage(): ISearchOperator {
// Do the normal jail behavior for non files
if ($this->storage->getItemType() !== 'file') {
return parent::getQueryFilterForStorage($builder);
return parent::getQueryFilterForStorage();
}
// for single file shares we don't need to do the LIKE
return $builder->expr()->andX(
parent::getQueryFilterForStorage($builder),
$builder->expr()->orX(
$builder->expr()->eq('path_hash', $builder->createNamedParameter(md5($this->getGetUnjailedRoot()))),
)
return new SearchBinaryOperator(
ISearchBinaryOperator::OPERATOR_AND,
[
\OC\Files\Cache\Cache::getQueryFilterForStorage(),
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
]
);
}
}

View File

@ -54,6 +54,7 @@ use OCP\Files\Cache\ICacheEntry;
use OCP\Files\FileInfo;
use OCP\Files\IMimeTypeLoader;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
use OCP\Files\Storage\IStorage;
use OCP\IDBConnection;
@ -1050,8 +1051,8 @@ class Cache implements ICache {
];
}
public function getQueryFilterForStorage(IQueryBuilder $builder) {
return $builder->expr()->eq('storage', $builder->createNamedParameter($this->getNumericStorageId(), IQueryBuilder::PARAM_INT));
public function getQueryFilterForStorage(): ISearchOperator {
return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', $this->getNumericStorageId());
}
public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {

View File

@ -22,10 +22,12 @@
namespace OC\Files\Cache;
use OC\Files\Search\SearchComparison;
use OCP\Constants;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
/**
@ -141,8 +143,8 @@ class FailedCache implements ICache {
throw new \Exception("Invalid cache");
}
public function getQueryFilterForStorage(IQueryBuilder $builder) {
return 'false';
public function getQueryFilterForStorage(): ISearchOperator {
return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', -1);
}
public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {

View File

@ -26,6 +26,7 @@
namespace OC\Files\Cache;
use OC\Files\Search\SearchBinaryOperator;
use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICache;
@ -48,7 +49,7 @@ class QuerySearchHelper {
ISearchComparison::COMPARE_GREATER_THAN => 'gt',
ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte',
ISearchComparison::COMPARE_LESS_THAN => 'lt',
ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte'
ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte',
];
protected static $searchOperatorNegativeMap = [
@ -57,7 +58,7 @@ class QuerySearchHelper {
ISearchComparison::COMPARE_GREATER_THAN => 'lte',
ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt',
ISearchComparison::COMPARE_LESS_THAN => 'gte',
ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt'
ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt',
];
public const TAG_FAVORITE = '_$!<Favorite>!$_';
@ -125,7 +126,7 @@ class QuerySearchHelper {
} else {
throw new \InvalidArgumentException('Binary operators inside "not" is not supported');
}
// no break
// no break
case ISearchBinaryOperator::OPERATOR_AND:
return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
case ISearchBinaryOperator::OPERATOR_OR:
@ -196,7 +197,8 @@ class QuerySearchHelper {
'size' => 'integer',
'tagname' => 'string',
'favorite' => 'boolean',
'fileid' => 'integer'
'fileid' => 'integer',
'storage' => 'integer',
];
$comparisons = [
'mimetype' => ['eq', 'like'],
@ -206,7 +208,8 @@ class QuerySearchHelper {
'size' => ['eq', 'gt', 'lt', 'gte', 'lte'],
'tagname' => ['eq', 'like'],
'favorite' => ['eq'],
'fileid' => ['eq']
'fileid' => ['eq'],
'storage' => ['eq'],
];
if (!isset($types[$operator->getField()])) {
@ -275,12 +278,6 @@ class QuerySearchHelper {
$query = $builder->selectFileCache('file');
$storageFilters = array_map(function (ICache $cache) use ($builder) {
return $cache->getQueryFilterForStorage($builder);
}, $caches);
$query->andWhere($query->expr()->orX(...$storageFilters));
if ($this->shouldJoinTags($searchQuery->getSearchOperation())) {
$user = $searchQuery->getUser();
if ($user === null) {
@ -301,6 +298,11 @@ class QuerySearchHelper {
$query->andWhere($searchExpr);
}
$storageFilters = array_map(function (ICache $cache) {
return $cache->getQueryFilterForStorage();
}, $caches);
$query->andWhere($this->searchOperatorToDBExpr($builder, new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters)));
if ($searchQuery->limitToHome() && ($this instanceof HomeCache)) {
$query->andWhere($builder->expr()->like('path', $query->expr()->literal('files/%')));
}

View File

@ -29,8 +29,12 @@
namespace OC\Files\Cache\Wrapper;
use OC\Files\Cache\Cache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
/**
* Jail to a subdirectory of the wrapped cache
@ -302,15 +306,17 @@ class CacheJail extends CacheWrapper {
return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath));
}
public function getQueryFilterForStorage(IQueryBuilder $builder) {
$escapedRoot = $builder->getConnection()->escapeLikeParameter($this->getGetUnjailedRoot());
return $builder->expr()->andX(
$this->getCache()->getQueryFilterForStorage($builder),
$builder->expr()->orX(
$builder->expr()->eq('path_hash', $builder->createNamedParameter(md5($this->getGetUnjailedRoot()))),
$builder->expr()->like('path', $builder->createNamedParameter($escapedRoot . '/%')),
)
public function getQueryFilterForStorage(): ISearchOperator {
return new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND,
[
$this->getCache()->getQueryFilterForStorage(),
new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR,
[
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $this->getGetUnjailedRoot() . '/%'),
],
)
]
);
}

View File

@ -32,9 +32,9 @@ namespace OC\Files\Cache\Wrapper;
use OC\Files\Cache\Cache;
use OC\Files\Cache\QuerySearchHelper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
class CacheWrapper extends Cache {
@ -310,8 +310,8 @@ class CacheWrapper extends Cache {
return parent::getById($id);
}
public function getQueryFilterForStorage(IQueryBuilder $builder) {
return $this->getCache()->getQueryFilterForStorage($builder);
public function getQueryFilterForStorage(): ISearchOperator {
return $this->getCache()->getQueryFilterForStorage();
}
public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {

View File

@ -24,11 +24,13 @@
namespace OC\Lockdown\Filesystem;
use OC\Files\Cache\CacheEntry;
use OC\Files\Search\SearchComparison;
use OCP\Constants;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\FileInfo;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
class NullCache implements ICache {
@ -129,8 +131,8 @@ class NullCache implements ICache {
throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
}
public function getQueryFilterForStorage(IQueryBuilder $builder) {
return 'false';
public function getQueryFilterForStorage(): ISearchOperator {
return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', -1);
}
public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {

View File

@ -23,8 +23,7 @@
namespace OCP\Files\Cache;
use OCP\DB\QueryBuilder\ICompositeExpression;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Search\ISearchOperator;
use OCP\Files\Search\ISearchQuery;
/**
@ -271,14 +270,13 @@ interface ICache {
/**
* Get the query expression required to filter files within this storage.
*
* In the most basic case this is just `$builder->expr()->eq('storage', $this->getNumericStorageId())`
* In the most basic case this is just comparing the storage id
* but storage wrappers can add additional expressions to filter down things further
*
* @param IQueryBuilder $builder
* @return string|ICompositeExpression
* @return ISearchOperator
* @since 22.0.0
*/
public function getQueryFilterForStorage(IQueryBuilder $builder);
public function getQueryFilterForStorage(): ISearchOperator;
/**
* Construct a cache entry from a search result row *if* the entry belongs to this storage.