1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-23 06:34:55 +00:00

Work around MySQL absurdities

This commit is contained in:
J. King 2022-06-04 22:07:21 -04:00
parent 2822864a85
commit c40f39e34e
4 changed files with 10 additions and 8 deletions

View file

@ -813,7 +813,8 @@ class Database {
public function subscriptionList(string $user, $folder = null, bool $recursive = true, int $id = null): Db\Result { public function subscriptionList(string $user, $folder = null, bool $recursive = true, int $id = null): Db\Result {
// validate inputs // validate inputs
$folder = $this->folderValidateId($user, $folder)['id']; $folder = $this->folderValidateId($user, $folder)['id'];
// create a complex query // compile the query
$integerType = $this->db->sqlToken("integer");
$q = new Query( $q = new Query(
"WITH RECURSIVE "WITH RECURSIVE
topmost(f_id, top) as ( topmost(f_id, top) as (
@ -834,7 +835,7 @@ class Database {
i.url as icon_url, i.url as icon_url,
folder, t.top as top_folder, d.name as folder_name, dt.name as top_folder_name, 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(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 from arsse_subscriptions as s
join arsse_feeds as f on f.id = s.feed join arsse_feeds as f on f.id = s.feed
left join topmost as t on t.f_id = s.folder 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 * @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 { public function labelList(string $user, bool $includeEmpty = true): Db\Result {
$integerType = $this->db->sqlToken("integer");
return $this->db->prepareArray( return $this->db->prepareArray(
"SELECT * FROM ( "SELECT * FROM (
SELECT SELECT
id, id,
name, name,
coalesce(articles - coalesce(hidden, 0), 0) as articles, cast(coalesce(articles - coalesce(hidden, 0), 0) as $integerType) as articles, -- this cast is required for MySQL for unclear reasons
coalesce(marked, 0) as \"read\" cast(coalesce(marked, 0) as $integerType) as \"read\" -- this cast is required for MySQL for unclear reasons
from arsse_labels from arsse_labels
left join ( left join (
SELECT label, sum(assigned) as articles from arsse_label_members group by label SELECT label, sum(assigned) as articles from arsse_label_members group by label

View file

@ -83,6 +83,8 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
return '"utf8mb4_unicode_ci"'; return '"utf8mb4_unicode_ci"';
case "asc": case "asc":
return ""; return "";
case "integer":
return "signed integer";
default: default:
return $token; return $token;
} }

View file

@ -384,6 +384,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
$greatest = $this->drv->sqlToken("GrEatESt"); $greatest = $this->drv->sqlToken("GrEatESt");
$nocase = $this->drv->sqlToken("noCASE"); $nocase = $this->drv->sqlToken("noCASE");
$like = $this->drv->sqlToken("liKe"); $like = $this->drv->sqlToken("liKe");
$integer = $this->drv->sqlToken("InTEGer");
$asc = $this->drv->sqlToken("asc"); $asc = $this->drv->sqlToken("asc");
$desc = $this->drv->sqlToken("desc"); $desc = $this->drv->sqlToken("desc");
$least = $this->drv->sqlToken("leASt"); $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 $greatest('Z', 'A')")->getValue());
$this->assertSame("Z", $this->drv->query("SELECT 'Z' collate $nocase")->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->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([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")); $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"));
} }

View file

@ -518,10 +518,6 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
// stringify our expectations if necessary // stringify our expectations if necessary
if (static::$stringOutput ?? false) { if (static::$stringOutput ?? false) {
$expected = $this->stringify($expected); $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).")"); $this->assertCount(sizeof($expected), $data, "Number of result rows (".sizeof($data).") differs from number of expected rows (".sizeof($expected).")");
if (sizeof($expected)) { if (sizeof($expected)) {