diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index 07b928e992..742d29e92c 100644 --- a/apps/dav/lib/carddav/carddavbackend.php +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -689,20 +689,24 @@ class CardDavBackend implements BackendInterface, SyncSupport { */ public function search($addressBookId, $pattern, $searchProperties) { $query = $this->db->getQueryBuilder(); - $query->select('carddata') - ->from($this->dbCardsTable, 'c') - ->leftJoin('c', $this->dbCardsPropertiesTable, 'cp', $query->expr()->eq('cp.cardid', 'c.id')); + $query2 = $this->db->getQueryBuilder(); + $query2->selectDistinct('cp.cardid')->from($this->dbCardsPropertiesTable, 'cp'); foreach ($searchProperties as $property) { - $query->orWhere( - $query->expr()->andX( - $query->expr()->eq('cp.name', $query->createNamedParameter($property)), - $query->expr()->like('cp.value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%')) - ) + $query2->orWhere( + $query2->expr()->andX( + $query2->expr()->eq('cp.name', $query->createNamedParameter($property)), + $query2->expr()->like('cp.value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%')) + ) ); } - $query->andWhere($query->expr()->eq('cp.addressbookid', $query->createNamedParameter($addressBookId))); - $result = $query->execute(); + $query2->andWhere($query2->expr()->eq('cp.addressbookid', $query->createNamedParameter($addressBookId))); + + $query->select('c.carddata')->from($this->dbCardsTable, 'c') + ->where($query->expr()->in('c.id', $query->createFunction($query2->getSQL()))); + + $result = $query->execute(); $cards = $result->fetchAll(); + $result->closeCursor(); return array_map(function($array) {return $this->readBlob($array['carddata']);}, $cards); diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php index 8feba950b7..56d04a8cd4 100644 --- a/apps/dav/tests/unit/carddav/carddavbackendtest.php +++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php @@ -393,12 +393,13 @@ class CardDavBackendTest extends TestCase { * @param string $pattern * @param array $expected */ - public function testSearch($pattern, $expected) { + public function testSearch($pattern, $properties, $expected) { /** @var VCard $vCards */ $vCards = []; $vCards[0] = new VCard(); $vCards[0]->add(new Text($vCards[0], 'UID', 'uid')); $vCards[0]->add(new Text($vCards[0], 'FN', 'John Doe')); + $vCards[0]->add(new Text($vCards[0], 'CLOUD', 'john@owncloud.org')); $vCards[1] = new VCard(); $vCards[1]->add(new Text($vCards[1], 'UID', 'uid')); $vCards[1]->add(new Text($vCards[1], 'FN', 'John M. Doe')); @@ -432,6 +433,17 @@ class CardDavBackendTest extends TestCase { ] ); $query->execute(); + $query->insert($this->dbCardsPropertiesTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(0), + 'cardid' => $query->createNamedParameter($vCardIds[0]), + 'name' => $query->createNamedParameter('CLOUD'), + 'value' => $query->createNamedParameter('John@owncloud.org'), + 'preferred' => $query->createNamedParameter(0) + ] + ); + $query->execute(); $query->insert($this->dbCardsPropertiesTable) ->values( [ @@ -444,7 +456,7 @@ class CardDavBackendTest extends TestCase { ); $query->execute(); - $result = $this->backend->search(0, $pattern, ['FN']); + $result = $this->backend->search(0, $pattern, $properties); // check result $this->assertSame(count($expected), count($result)); @@ -463,9 +475,11 @@ class CardDavBackendTest extends TestCase { public function dataTestSearch() { return [ - ['John', ['John Doe', 'John M. Doe']], - ['M. Doe', ['John M. Doe']], - ['Do', ['John Doe', 'John M. Doe']] + ['John', ['FN'], ['John Doe', 'John M. Doe']], + ['M. Doe', ['FN'], ['John M. Doe']], + ['Do', ['FN'], ['John Doe', 'John M. Doe']], + // check if duplicates are handled correctly + ['John', ['FN', 'CLOUD'], ['John Doe', 'John M. Doe']], ]; }