From 7467422f570a44d3b3865907ba6f6f1a96d53a0b Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Wed, 15 Nov 2023 20:02:28 -0100 Subject: [PATCH] implements search on null/notnull metadata Signed-off-by: Maxence Lange --- apps/dav/lib/Files/FileSearchBackend.php | 31 +++++++++++++------ lib/private/Files/Cache/SearchBuilder.php | 2 ++ lib/public/Files/Search/ISearchComparison.php | 1 + 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php index 3500d6b0fb3..d52eb60729a 100644 --- a/apps/dav/lib/Files/FileSearchBackend.php +++ b/apps/dav/lib/Files/FileSearchBackend.php @@ -39,6 +39,7 @@ use OCP\Files\Cache\ICacheEntry; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Node; +use OCP\Files\Search\ISearchComparison; use OCP\Files\Search\ISearchOperator; use OCP\Files\Search\ISearchOrder; use OCP\Files\Search\ISearchQuery; @@ -367,22 +368,30 @@ class FileSearchBackend implements ISearchBackend { if (count($operator->arguments) !== 2) { throw new \InvalidArgumentException('Invalid number of arguments for ' . $trimmedType . ' operation'); } - if (!($operator->arguments[0] instanceof SearchPropertyDefinition)) { - throw new \InvalidArgumentException('Invalid argument 1 for ' . $trimmedType . ' operation, expected property'); - } if (!($operator->arguments[1] instanceof Literal)) { throw new \InvalidArgumentException('Invalid argument 2 for ' . $trimmedType . ' operation, expected literal'); } - + $value = $operator->arguments[1]->value; + case Operator::OPERATION_IS_DEFINED: + if (!($operator->arguments[0] instanceof SearchPropertyDefinition)) { + throw new \InvalidArgumentException('Invalid argument 1 for ' . $trimmedType . ' operation, expected property'); + } $property = $operator->arguments[0]; - $value = $this->castValue($property, $operator->arguments[1]->value); + if (str_starts_with($property->name, FilesPlugin::FILE_METADATA_PREFIX)) { - return new SearchComparison($trimmedType, substr($property->name, strlen(FilesPlugin::FILE_METADATA_PREFIX)), $value, IMetadataQuery::EXTRA); + $field = substr($property->name, strlen(FilesPlugin::FILE_METADATA_PREFIX)); + $extra = IMetadataQuery::EXTRA; } else { - return new SearchComparison($trimmedType, $this->mapPropertyNameToColumn($property), $value); + $field = $this->mapPropertyNameToColumn($property); } - // no break + return new SearchComparison( + ISearchComparison::COMPARE_DEFINED, + $field, + $this->castValue($property, $value ?? ''), + $extra ?? '' + ); + case Operator::OPERATION_IS_COLLECTION: return new SearchComparison('eq', 'mimetype', ICacheEntry::DIRECTORY_MIMETYPE); default: @@ -416,7 +425,11 @@ class FileSearchBackend implements ISearchBackend { } private function castValue(SearchPropertyDefinition $property, $value) { - switch ($property->dataType) { + if ($value === '') { + return ''; + } + + switch ($property->dataType) { case SearchPropertyDefinition::DATATYPE_BOOLEAN: return $value === 'yes'; case SearchPropertyDefinition::DATATYPE_DECIMAL: diff --git a/lib/private/Files/Cache/SearchBuilder.php b/lib/private/Files/Cache/SearchBuilder.php index c3699cca63d..38161ec9cc6 100644 --- a/lib/private/Files/Cache/SearchBuilder.php +++ b/lib/private/Files/Cache/SearchBuilder.php @@ -47,6 +47,7 @@ class SearchBuilder { ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte', ISearchComparison::COMPARE_LESS_THAN => 'lt', ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte', + ISearchComparison::COMPARE_DEFINED => 'isNotNull', ]; protected static $searchOperatorNegativeMap = [ @@ -57,6 +58,7 @@ class SearchBuilder { ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt', ISearchComparison::COMPARE_LESS_THAN => 'gte', ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'gt', + ISearchComparison::COMPARE_DEFINED => 'isNull', ]; public const TAG_FAVORITE = '_$!!$_'; diff --git a/lib/public/Files/Search/ISearchComparison.php b/lib/public/Files/Search/ISearchComparison.php index d7313fbaf2a..e1650dabc61 100644 --- a/lib/public/Files/Search/ISearchComparison.php +++ b/lib/public/Files/Search/ISearchComparison.php @@ -35,6 +35,7 @@ interface ISearchComparison extends ISearchOperator { public const COMPARE_LESS_THAN_EQUAL = 'lte'; public const COMPARE_LIKE = 'like'; public const COMPARE_LIKE_CASE_SENSITIVE = 'clike'; + public const COMPARE_DEFINED = 'defined'; public const HINT_PATH_EQ_HASH = 'path_eq_hash'; // transform `path = "$path"` into `path_hash = md5("$path")`, on by default -- 2.39.5