From c40f39e34e8b5d1405e9030c018ef1a9da750b8a Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sat, 4 Jun 2022 22:07:21 -0400 Subject: [PATCH] Work around MySQL absurdities --- lib/Database.php | 10 ++++++---- lib/Db/MySQL/Driver.php | 2 ++ tests/cases/Db/BaseDriver.php | 2 ++ tests/lib/AbstractTest.php | 4 ---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/Database.php b/lib/Database.php index 87a3c56..68cc43d 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -813,7 +813,8 @@ class Database { public function subscriptionList(string $user, $folder = null, bool $recursive = true, int $id = null): Db\Result { // validate inputs $folder = $this->folderValidateId($user, $folder)['id']; - // create a complex query + // compile the query + $integerType = $this->db->sqlToken("integer"); $q = new Query( "WITH RECURSIVE topmost(f_id, top) as ( @@ -834,7 +835,7 @@ class Database { i.url as icon_url, folder, t.top as top_folder, d.name as folder_name, dt.name as top_folder_name, coalesce(s.title, f.title) as title, - coalesce((articles - hidden - marked), coalesce(articles,0)) as unread + cast(coalesce((articles - hidden - marked), coalesce(articles,0)) as $integerType) as unread -- this cast is required for MySQL for unclear reasons from arsse_subscriptions as s join arsse_feeds as f on f.id = s.feed left join topmost as t on t.f_id = s.folder @@ -2209,13 +2210,14 @@ class Database { * @param boolean $includeEmpty Whether to include (true) or supress (false) labels which have no articles assigned to them */ public function labelList(string $user, bool $includeEmpty = true): Db\Result { + $integerType = $this->db->sqlToken("integer"); return $this->db->prepareArray( "SELECT * FROM ( SELECT id, name, - coalesce(articles - coalesce(hidden, 0), 0) as articles, - coalesce(marked, 0) as \"read\" + cast(coalesce(articles - coalesce(hidden, 0), 0) as $integerType) as articles, -- this cast is required for MySQL for unclear reasons + cast(coalesce(marked, 0) as $integerType) as \"read\" -- this cast is required for MySQL for unclear reasons from arsse_labels left join ( SELECT label, sum(assigned) as articles from arsse_label_members group by label diff --git a/lib/Db/MySQL/Driver.php b/lib/Db/MySQL/Driver.php index 532d05d..10bc766 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 "asc": return ""; + case "integer": + return "signed integer"; default: return $token; } diff --git a/tests/cases/Db/BaseDriver.php b/tests/cases/Db/BaseDriver.php index 0999d3a..fe7f344 100644 --- a/tests/cases/Db/BaseDriver.php +++ b/tests/cases/Db/BaseDriver.php @@ -384,6 +384,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { $greatest = $this->drv->sqlToken("GrEatESt"); $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"); $least = $this->drv->sqlToken("leASt"); @@ -394,6 +395,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame("Z", $this->drv->query("SELECT $greatest('Z', 'A')")->getValue()); $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, 2], array_column($this->drv->query("SELECT 1 as t union select null as t union select 2 as t order by t $asc")->getAll(), "t")); $this->assertEquals([2, 1, null], array_column($this->drv->query("SELECT 1 as t union select null as t union select 2 as t order by t $desc")->getAll(), "t")); } diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index d352bd6..a22913d 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -518,10 +518,6 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { // stringify our expectations if necessary if (static::$stringOutput ?? false) { $expected = $this->stringify($expected); - // MySQL is extra-special and mixes strings and integers, so we cast the data, too - if ((static::$implementation ?? "") === "MySQL") { - $data = $this->stringify($data); - } } $this->assertCount(sizeof($expected), $data, "Number of result rows (".sizeof($data).") differs from number of expected rows (".sizeof($expected).")"); if (sizeof($expected)) {