Browse Source

Work around MySQL absurdities

dbtest
J. King 2 years ago
parent
commit
c40f39e34e
  1. 10
      lib/Database.php
  2. 2
      lib/Db/MySQL/Driver.php
  3. 2
      tests/cases/Db/BaseDriver.php
  4. 4
      tests/lib/AbstractTest.php

10
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

2
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;
}

2
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"));
}

4
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)) {

Loading…
Cancel
Save