Fixed issue with postgres when fetching resultset ordering by nullable column

This commit is contained in:
Alejandro Celaya 2019-10-04 17:54:19 +02:00
parent eced1af21d
commit 8d3a49a319
2 changed files with 9 additions and 4 deletions

View File

@ -119,6 +119,11 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
public function findOneByShortCode(string $shortCode, ?string $domain = null): ?ShortUrl
{
// When ordering DESC, Postgres puts nulls at the beginning while the rest of supported DB engines put them at
// the bottom
$dbPlatform = $this->getEntityManager()->getConnection()->getDatabasePlatform()->getName();
$ordering = $dbPlatform === 'postgresql' ? 'ASC' : 'DESC';
$dql= <<<DQL
SELECT s
FROM Shlinkio\Shlink\Core\Entity\ShortUrl AS s
@ -127,7 +132,7 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
AND (s.validSince <= :now OR s.validSince IS NULL)
AND (s.validUntil >= :now OR s.validUntil IS NULL)
AND (s.domain IS NULL OR d.authority = :domain)
ORDER BY s.domain DESC
ORDER BY s.domain {$ordering}
DQL;
$query = $this->getEntityManager()->createQuery($dql);
@ -138,8 +143,8 @@ DQL;
'domain' => $domain,
]);
// Since we ordered by domain DESC, we will have first the URL matching the domain, followed
// by the one with no domain (if any), so it is safe to fetch 1 max result and we will get:
// Since we ordered by domain, we will have first the URL matching provided domain, followed by the one
// with no domain (if any), so it is safe to fetch 1 max result and we will get:
// * The short URL matching both the short code and the domain, or
// * The short URL matching the short code but without any domain, or
// * No short URL at all

View File

@ -63,7 +63,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
$withDomain->setShortCode('domain-short-code');
$this->getEntityManager()->persist($withDomain);
$withDomainDuplicatingRegular = new ShortUrl('foo', ShortUrlMeta::createFromRawData([
$withDomainDuplicatingRegular = new ShortUrl('foo_with_domain', ShortUrlMeta::createFromRawData([
'domain' => 'doma.in',
]));
$withDomainDuplicatingRegular->setShortCode('foo');