]> source.dussan.org Git - nextcloud-server.git/commitdiff
implements search on null/notnull metadata
authorMaxence Lange <maxence@artificial-owl.com>
Wed, 15 Nov 2023 21:02:28 +0000 (20:02 -0100)
committerMaxence Lange <maxence@artificial-owl.com>
Wed, 22 Nov 2023 13:43:27 +0000 (12:43 -0100)
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
apps/dav/lib/Files/FileSearchBackend.php
lib/private/Files/Cache/SearchBuilder.php
lib/public/Files/Search/ISearchComparison.php

index 3500d6b0fb3eb418a88123084dccf97c4b10b06b..d52eb60729a9aabbd10bd41ffc33810a202d6ff4 100644 (file)
@@ -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:
index c3699cca63d0290be023369f84686039804ddf23..38161ec9cc622403c6720931c4f119a0f959d564 100644 (file)
@@ -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 = '_$!<Favorite>!$_';
index d7313fbaf2a5dbe25401570f01cdc74937092e15..e1650dabc612ad6230cccf6362d605c5764af197 100644 (file)
@@ -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