Ensure ordering by title is consistent between database engines

This commit is contained in:
Alejandro Celaya 2024-03-29 09:35:54 +01:00
parent 7f4137e7cc
commit 90514c603f
3 changed files with 19 additions and 15 deletions

View file

@ -124,15 +124,15 @@
"test:db": "@parallel test:db:sqlite:ci test:db:mysql test:db:maria test:db:postgres test:db:ms",
"test:db:sqlite": "APP_ENV=test php vendor/bin/phpunit --order-by=random --colors=always --testdox -c phpunit-db.xml",
"test:db:sqlite:ci": "@test:db:sqlite --coverage-php build/coverage-db.cov",
"test:db:mysql": "DB_DRIVER=mysql composer test:db:sqlite",
"test:db:maria": "DB_DRIVER=maria composer test:db:sqlite",
"test:db:postgres": "DB_DRIVER=postgres composer test:db:sqlite",
"test:db:ms": "DB_DRIVER=mssql composer test:db:sqlite",
"test:db:mysql": "DB_DRIVER=mysql composer test:db:sqlite -- $*",
"test:db:maria": "DB_DRIVER=maria composer test:db:sqlite -- $*",
"test:db:postgres": "DB_DRIVER=postgres composer test:db:sqlite -- $*",
"test:db:ms": "DB_DRIVER=mssql composer test:db:sqlite -- $*",
"test:api": "bin/test/run-api-tests.sh",
"test:api:sqlite": "DB_DRIVER=sqlite composer test:api",
"test:api:mysql": "DB_DRIVER=mysql composer test:api",
"test:api:maria": "DB_DRIVER=maria composer test:api",
"test:api:mssql": "DB_DRIVER=mssql composer test:api",
"test:api:sqlite": "DB_DRIVER=sqlite composer test:api -- $*",
"test:api:mysql": "DB_DRIVER=mysql composer test:api -- $*",
"test:api:maria": "DB_DRIVER=maria composer test:api -- $*",
"test:api:mssql": "DB_DRIVER=mssql composer test:api -- $*",
"test:api:ci": "GENERATE_COVERAGE=yes composer test:api && vendor/bin/phpcov merge build/coverage-api --php build/coverage-api.cov && rm build/coverage-api/*.cov",
"test:api:pretty": "GENERATE_COVERAGE=yes composer test:api && vendor/bin/phpcov merge build/coverage-api --html build/coverage-api/coverage-html && rm build/coverage-api/*.cov",
"test:cli": "APP_ENV=test DB_DRIVER=maria TEST_ENV=cli php vendor/bin/phpunit --order-by=random --colors=always --testdox -c phpunit-cli.xml",

View file

@ -46,6 +46,8 @@ class ShortUrlListRepository extends EntitySpecificationRepository implements Sh
'DISTINCT s AS shortUrl',
'(' . $buildVisitsSubQuery('v', excludingBots: false) . ') AS ' . OrderableField::VISITS->value,
'(' . $buildVisitsSubQuery('v2', excludingBots: true) . ') AS ' . OrderableField::NON_BOT_VISITS->value,
// This is added only to have a consistent order by title between database engines
'COALESCE(s.title, \'\') AS title',
)
->setMaxResults($filtering->limit)
->setFirstResult($filtering->offset)
@ -62,15 +64,17 @@ class ShortUrlListRepository extends EntitySpecificationRepository implements Sh
private function processOrderByForList(QueryBuilder $qb, ShortUrlsListFiltering $filtering): void
{
$fieldName = $filtering->orderBy->field;
$order = $filtering->orderBy->direction;
match (true) {
$direction = $filtering->orderBy->direction;
[$sort, $order] = match (true) {
// With no explicit order by, fallback to dateCreated-DESC
$fieldName === null => $qb->orderBy('s.dateCreated', 'DESC'),
$fieldName === null => ['s.dateCreated', 'DESC'],
$fieldName === OrderableField::VISITS->value,
$fieldName === OrderableField::NON_BOT_VISITS->value => $qb->orderBy($fieldName, $order),
default => $qb->orderBy('s.' . $fieldName, $order),
$fieldName === OrderableField::NON_BOT_VISITS->value,
$fieldName === OrderableField::TITLE->value => [$fieldName, $direction],
default => ['s.' . $fieldName, $direction],
};
$qb->orderBy($sort, $order);
}
public function countList(ShortUrlsCountFiltering $filtering): int

View file

@ -201,12 +201,12 @@ class ListShortUrlsTest extends ApiTestCase
self::SHORT_URL_SHLINK_WITH_TITLE,
], 'valid_api_key'];
yield [['orderBy' => 'title-DESC'], [
self::SHORT_URL_SHLINK_WITH_TITLE,
self::SHORT_URL_META,
self::SHORT_URL_CUSTOM_SLUG,
self::SHORT_URL_DOCS,
self::SHORT_URL_CUSTOM_DOMAIN,
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
self::SHORT_URL_SHLINK_WITH_TITLE,
], 'valid_api_key'];
yield [['startDate' => Chronos::parse('2018-12-01')->toAtomString()], [
self::SHORT_URL_CUSTOM_DOMAIN,