Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
do cachejail search filtering in sql
Signed-off-by: Robin Appelman <[email protected]>
  • Loading branch information
icewind1991 committed Jan 26, 2021
commit a44aab11f726dfe9bacb38339e2da59cdeb8f467
2 changes: 1 addition & 1 deletion lib/private/Files/Cache/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public function __construct(IStorage $storage) {
$this->querySearchHelper = new QuerySearchHelper($this->mimetypeLoader);
}

private function getQueryBuilder() {
protected function getQueryBuilder() {
return new CacheQueryBuilder(
$this->connection,
\OC::$server->getSystemConfig(),
Expand Down
2 changes: 2 additions & 0 deletions lib/private/Files/Cache/QuerySearchHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ private function validateComparison(ISearchComparison $operator) {
'mimetype' => 'string',
'mtime' => 'integer',
'name' => 'string',
'path' => 'string',
'size' => 'integer',
'tagname' => 'string',
'favorite' => 'boolean',
Expand All @@ -184,6 +185,7 @@ private function validateComparison(ISearchComparison $operator) {
'mimetype' => ['eq', 'like'],
'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'],
'name' => ['eq', 'like'],
'path' => ['eq', 'like'],
'size' => ['eq', 'gt', 'lt', 'gte', 'lte'],
'tagname' => ['eq', 'like'],
'favorite' => ['eq'],
Expand Down
60 changes: 57 additions & 3 deletions lib/private/Files/Cache/Wrapper/CacheJail.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@
namespace OC\Files\Cache\Wrapper;

use OC\Files\Cache\Cache;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
use OCP\Files\Search\ISearchQuery;

/**
Expand All @@ -49,6 +54,8 @@ class CacheJail extends CacheWrapper {
public function __construct($cache, $root) {
parent::__construct($cache);
$this->root = $root;
$this->connection = \OC::$server->getDatabaseConnection();
$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
}

protected function getRoot() {
Expand Down Expand Up @@ -221,7 +228,26 @@ private function formatSearchResults($results) {
* @return array an array of file data
*/
public function search($pattern) {
$results = $this->getCache()->search($pattern);
// normalize pattern
$pattern = $this->normalize($pattern);

if ($pattern === '%%') {
return [];
}

$query = $this->getQueryBuilder();
$query->selectFileCache()
->whereStorageId()
->andWhere($query->expr()->like('path', $query->createNamedParameter($this->getRoot() . '/%')))
->andWhere($query->expr()->iLike('name', $query->createNamedParameter($pattern)));

$result = $query->execute();
$files = $result->fetchAll();
$result->closeCursor();

$results = array_map(function (array $data) {
return self::cacheEntryFromData($data, $this->mimetypeLoader);
}, $files);
return $this->formatSearchResults($results);
}

Expand All @@ -232,12 +258,40 @@ public function search($pattern) {
* @return array
*/
public function searchByMime($mimetype) {
$results = $this->getCache()->searchByMime($mimetype);
$mimeId = $this->mimetypeLoader->getId($mimetype);

$query = $this->getQueryBuilder();
$query->selectFileCache()
->whereStorageId()
->andWhere($query->expr()->like('path', $query->createNamedParameter($this->getRoot() . '/%')));

if (strpos($mimetype, '/')) {
$query->andWhere($query->expr()->eq('mimetype', $query->createNamedParameter($mimeId, IQueryBuilder::PARAM_INT)));
} else {
$query->andWhere($query->expr()->eq('mimepart', $query->createNamedParameter($mimeId, IQueryBuilder::PARAM_INT)));
}

$result = $query->execute();
$files = $result->fetchAll();
$result->closeCursor();

$results = array_map(function (array $data) {
return self::cacheEntryFromData($data, $this->mimetypeLoader);
}, $files);
return $this->formatSearchResults($results);
}

public function searchQuery(ISearchQuery $query) {
$simpleQuery = new SearchQuery($query->getSearchOperation(), 0, 0, $query->getOrder(), $query->getUser());
$prefixFilter = new SearchComparison(
ISearchComparison::COMPARE_LIKE,
'path',
$this->getRoot() . '/%'
);
$operation = new SearchBinaryOperator(
ISearchBinaryOperator::OPERATOR_AND,
[$prefixFilter, $query->getSearchOperation()]
);
$simpleQuery = new SearchQuery($operation, 0, 0, $query->getOrder(), $query->getUser());
$results = $this->getCache()->searchQuery($simpleQuery);
$results = $this->formatSearchResults($results);

Expand Down
37 changes: 37 additions & 0 deletions tests/lib/Files/Cache/Wrapper/CacheJailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
namespace Test\Files\Cache\Wrapper;

use OC\Files\Cache\Wrapper\CacheJail;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
use OC\User\User;
use OCP\Files\Search\ISearchComparison;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\Files\Cache\CacheTest;

/**
Expand Down Expand Up @@ -46,6 +51,38 @@ public function testSearchOutsideJail() {
$this->assertEquals('foobar', $result[0]['path']);
}

public function testSearchMimeOutsideJail() {
$file1 = 'foo/foobar';
$file2 = 'folder/foobar';
$data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'];

$this->sourceCache->put($file1, $data1);
$this->sourceCache->put($file2, $data1);

$this->assertCount(2, $this->sourceCache->searchByMime('foo/folder'));

$result = $this->cache->search('%foobar%');
$this->assertCount(1, $result);
$this->assertEquals('foobar', $result[0]['path']);
}

public function testSearchQueryOutsideJail() {
$file1 = 'foo/foobar';
$file2 = 'folder/foobar';
$data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'];

$this->sourceCache->put($file1, $data1);
$this->sourceCache->put($file2, $data1);

$user = new User('foo', null, $this->createMock(EventDispatcherInterface::class));
$query = new SearchQuery(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', 'foobar'), 10, 0, [], $user);
$this->assertCount(2, $this->sourceCache->searchQuery($query));

$result = $this->cache->search('%foobar%');
$this->assertCount(1, $result);
$this->assertEquals('foobar', $result[0]['path']);
}

public function testClearKeepEntriesOutsideJail() {
$file1 = 'foo/foobar';
$file2 = 'foo/foobar/asd';
Expand Down