From ed27e0aaaa5e9165ee305eab10bca536d9be6f92 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Tue, 2 Feb 2021 10:00:08 -0500 Subject: [PATCH] Sort nulls consistently PostgreSQL normally sorts nulls after everything else in ascending order and vice versa; we reverse this, to match SQLIte and MySQL --- lib/Db/Driver.php | 2 ++ lib/Db/MySQL/Driver.php | 2 ++ lib/Db/PostgreSQL/Driver.php | 4 ++++ lib/Db/SQLite3/Driver.php | 2 ++ tests/cases/Db/BaseDriver.php | 4 ++++ 5 files changed, 14 insertions(+) diff --git a/lib/Db/Driver.php b/lib/Db/Driver.php index d533b92..cc522dc 100644 --- a/lib/Db/Driver.php +++ b/lib/Db/Driver.php @@ -75,6 +75,8 @@ interface Driver { * - "nocase": the name of a general-purpose case-insensitive collation sequence * - "like": the case-insensitive LIKE operator * - "integer": the integer type to use for explicit casts + * - "asc": ascending sort order + * - "desc": descending sort order */ public function sqlToken(string $token): string; diff --git a/lib/Db/MySQL/Driver.php b/lib/Db/MySQL/Driver.php index 8a82be4..1c0da1e 100644 --- a/lib/Db/MySQL/Driver.php +++ b/lib/Db/MySQL/Driver.php @@ -83,6 +83,8 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { return '"utf8mb4_unicode_ci"'; case "integer": return "signed integer"; + case "asc": + return ""; default: return $token; } diff --git a/lib/Db/PostgreSQL/Driver.php b/lib/Db/PostgreSQL/Driver.php index fccc071..c22f096 100644 --- a/lib/Db/PostgreSQL/Driver.php +++ b/lib/Db/PostgreSQL/Driver.php @@ -119,6 +119,10 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { return '"und-x-icu"'; case "like": return "ilike"; + case "asc": + return "nulls first"; + case "desc": + return "desc nulls last"; default: return $token; } diff --git a/lib/Db/SQLite3/Driver.php b/lib/Db/SQLite3/Driver.php index bef5ec6..3445b89 100644 --- a/lib/Db/SQLite3/Driver.php +++ b/lib/Db/SQLite3/Driver.php @@ -114,6 +114,8 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { switch (strtolower($token)) { case "greatest": return "max"; + case "asc": + return ""; default: return $token; } diff --git a/tests/cases/Db/BaseDriver.php b/tests/cases/Db/BaseDriver.php index 665443d..f47bcf0 100644 --- a/tests/cases/Db/BaseDriver.php +++ b/tests/cases/Db/BaseDriver.php @@ -385,6 +385,8 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { $nocase = $this->drv->sqlToken("noCASE"); $like = $this->drv->sqlToken("liKe"); $integer = $this->drv->sqlToken("InTEGer"); + $asc = $this->drv->sqlToken("asc"); + $desc = $this->drv->sqlToken("desc"); $this->assertSame("NOT_A_TOKEN", $this->drv->sqlToken("NOT_A_TOKEN")); @@ -392,5 +394,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame("Z", $this->drv->query("SELECT 'Z' collate $nocase")->getValue()); $this->assertSame("Z", $this->drv->query("SELECT 'Z' where 'Z' $like 'z'")->getValue()); $this->assertEquals(1, $this->drv->query("SELECT CAST((1=1) as $integer)")->getValue()); + $this->assertEquals([null, 1], array_column($this->drv->query("SELECT 1 as t union select null as t order by t $asc")->getAll(), "t")); + $this->assertEquals([1, null], array_column($this->drv->query("SELECT 1 as t union select null as t order by t $desc")->getAll(), "t")); } }