]> source.dussan.org Git - nextcloud-server.git/commitdiff
Reduce load of the contacts search when we know it can't match 21222/head
authorJoas Schilling <coding@schilljs.com>
Thu, 4 Jun 2020 08:23:23 +0000 (10:23 +0200)
committerJoas Schilling <coding@schilljs.com>
Mon, 15 Jun 2020 06:47:30 +0000 (08:47 +0200)
Signed-off-by: Joas Schilling <coding@schilljs.com>
apps/dav/lib/CardDAV/CardDavBackend.php
apps/dav/tests/unit/CardDAV/CardDavBackendTest.php

index 40b48f69ae028d079738d4fb479e476ee54cddd4..8fb48d062d09a102bed5cc7eb483b5ca88d8d6c3 100644 (file)
@@ -949,20 +949,38 @@ class CardDavBackend implements BackendInterface, SyncSupport {
         * @return array an array of contacts which are arrays of key-value-pairs
         */
        public function search($addressBookId, $pattern, $searchProperties, $options = []) {
-               $query2 = $this->db->getQueryBuilder();
+               $escapePattern = !\array_key_exists('escape_like_param', $options) || $options['escape_like_param'] !== false;
 
-               $query2->selectDistinct('cp.cardid')
-                       ->from($this->dbCardsPropertiesTable, 'cp')
-                       ->andWhere($query2->expr()->eq('cp.addressbookid', $query2->createNamedParameter($addressBookId)));
+               $query2 = $this->db->getQueryBuilder();
                $or = $query2->expr()->orX();
                foreach ($searchProperties as $property) {
+                       if ($escapePattern) {
+                               if ($property === 'EMAIL' && strpos($pattern, ' ') !== false) {
+                                       // There can be no spaces in emails
+                                       continue;
+                               }
+
+                               if ($property === 'CLOUD' && preg_match('/[^a-zA-Z0-9 _.@\-\']/', $pattern) === 1) {
+                                       // There can be no chars in cloud ids which are not valid for user ids
+                                       continue;
+                               }
+                       }
+
                        $or->add($query2->expr()->eq('cp.name', $query2->createNamedParameter($property)));
                }
-               $query2->andWhere($or);
+
+               if ($or->count() === 0) {
+                       return [];
+               }
+
+               $query2->selectDistinct('cp.cardid')
+                       ->from($this->dbCardsPropertiesTable, 'cp')
+                       ->andWhere($query2->expr()->eq('cp.addressbookid', $query2->createNamedParameter($addressBookId)))
+                       ->andWhere($or);
 
                // No need for like when the pattern is empty
                if ('' !== $pattern) {
-                       if (\array_key_exists('escape_like_param', $options) && $options['escape_like_param'] === false) {
+                       if (!$escapePattern) {
                                $query2->andWhere($query2->expr()->ilike('cp.value', $query2->createNamedParameter($pattern)));
                        } else {
                                $query2->andWhere($query2->expr()->ilike('cp.value', $query2->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%')));
index 27139dfd470118d35569b157d090a8887c6ddb18..c32aad5a056d114875741f33d587e6f4030ea690 100644 (file)
@@ -762,7 +762,7 @@ class CardDavBackendTest extends TestCase {
                        'limit' => ['john', ['FN'], ['limit' => 1], [['uri0', 'John Doe']]],
                        'limit and offset' => ['john', ['FN'], ['limit' => 1, 'offset' => 1], [['uri1', 'John M. Doe']]],
                        'find "_" escaped' => ['_', ['CLOUD'], [], [['uri2', 'find without options']]],
-                       'find not empty ClOUD' => ['%_%', ['CLOUD'], ['escape_like_param'=>false], [['uri0', 'John Doe'], ['uri2', 'find without options']]],
+                       'find not empty CLOUD' => ['%_%', ['CLOUD'], ['escape_like_param'=>false], [['uri0', 'John Doe'], ['uri2', 'find without options']]],
                ];
        }