add request_vote_summary table for ordering searches

This commit is contained in:
Spine
2025-06-11 08:50:36 +00:00
parent 8f46a185cb
commit 225c4c66cb
8 changed files with 126 additions and 52 deletions

View File

@@ -106,10 +106,15 @@ class Pg {
public function prepared_query(string $query, ...$args): int {
$begin = microtime(true);
$st = $this->prepare($query);
if ($st->execute([...$args])) {
$rowCount = $st->rowCount();
$this->stats->register($query, $rowCount, $begin, [...$args]);
return $rowCount;
try {
if ($st->execute([...$args])) {
$rowCount = $st->rowCount();
$this->stats->register($query, $rowCount, $begin, [...$args]);
return $rowCount;
}
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage()
. " $query " . json_encode($args, JSON_UNESCAPED_SLASHES));
}
$this->stats->error($query);
return 0;

View File

@@ -27,6 +27,7 @@ class Request extends \Gazelle\BaseManager {
Media $media,
LogCue $logCue,
string $oclc,
array $tagList = [],
int|null $groupId = null,
): \Gazelle\Request {
self::$db->prepared_query('
@@ -41,6 +42,30 @@ class Request extends \Gazelle\BaseManager {
$logCue->dbValue(), $logCue->needLogChecksum ? 1 : 0, $oclc, $groupId
);
$request = new \Gazelle\Request(self::$db->inserted_id());
$this->pg()->prepared_query("
insert into request (
id_request, id_user, id_tgroup, id_category, id_release_type, year,
last_vote, created, modified,
description, title, image, catalogue_number, record_label,
log_score, need_log, need_cue, need_checksum,
artist_title_ts, encoding_str, format_str, media_str, tag
) values (
?, ?, ?, ?, ?, ?,
?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?,
to_tsvector('simple', ?),
array[" . placeholders($encoding->dbList()) . "]::text[],
array[" . placeholders($format->dbList()) . "]::text[],
array[" . placeholders($media->dbList()) . "]::text[],
array[" . placeholders($tagList) . "]::int[]
)
", $request->id, $user->id, $groupId, $categoryId, $releaseType, $year,
$request->lastVoteDate(), $request->created(), $request->modified(),
$description, $title, $image, $catalogueNumber, $recordLabel,
$logCue->minScore, $logCue->needLog ? 't' : 'f', $logCue->needCue ? 't' : 'f', $logCue->needLogChecksum ? 't' : 'f',
$title, ...$encoding->dbList(), ...$format->dbList(), ...$media->dbList(), ...$tagList,
);
$request->vote($user, $bounty);
$request->artistFlush();
return $request;
@@ -177,8 +202,10 @@ class Request extends \Gazelle\BaseManager {
coalesce(position('Log' in rr.\"LogCue\") > 0, false) as need_log,
coalesce(position('Cue' in rr.\"LogCue\") > 0, false) as need_cue,
case when rr.\"Checksum\" = 0 then false else true end as need_checksum,
rr.\"BitrateList\" as encoding, rr.\"FormatList\" as format, rr.\"MediaList\" as media,
a_t.artist_title_ts,
string_to_array(rr.\"BitrateList\", '|') as encoding_str,
string_to_array(rr.\"FormatList\", '|') as format_str,
string_to_array(rr.\"MediaList\", '|') as media_str,
coalesce(tl.tag, ARRAY[]::int[]) as tag
from relay.requests rr
inner join a_t on (a_t.id_request = rr.\"ID\")
@@ -186,41 +213,38 @@ class Request extends \Gazelle\BaseManager {
) as i on r.id_request = i.id_request
when not matched then
insert (
id_request, id_user, id_filler, id_torrent,
id_tgroup, id_category, id_release_type, year,
last_vote, filled, created, modified,
description, title, image, catalogue_number,
record_label, log_score,
need_log, need_cue, need_checksum,
encoding_str, format_str, media_str,
artist_title_ts, tag
id_request, id_user, id_tgroup, id_category,
id_release_type, year,
last_vote, created, modified,
description, title, image, catalogue_number, record_label,
log_score, need_log, need_cue, need_checksum,
artist_title_ts, tag, encoding_str, format_str, media_str
) values (
i.id_request, i.id_user, i.id_filler, i.id_torrent,
i.id_tgroup, i.id_category, i.id_release_type, i.year,
i.last_vote, i.filled, i.created, i.updated,
i.description, i.title, i.image, i.catalogue_number,
i.record_label, i.log_score,
i.need_log, i.need_cue, i.need_checksum,
string_to_array(i.encoding::text, '|'),
string_to_array(i.format::text, '|'),
string_to_array(i.media::text, '|'),
i.artist_title_ts, i.tag
i.id_request, i.id_user, i.id_tgroup, i.id_category,
i.id_release_type, i.year,
i.last_vote, i.created, i.updated,
i.description, i.title, i.image, i.catalogue_number, i.record_label,
i.log_score, i.need_log, i.need_cue, i.need_checksum,
i.artist_title_ts,
i.tag,
string_to_array(i.encoding_str::text, '|'),
string_to_array(i.format_str::text, '|'),
string_to_array(i.media_str::text, '|')
)
when matched then
update set
id_user = i.id_user, id_filler = i.id_filler, id_torrent = i.id_torrent,
id_tgroup = i.id_tgroup, id_category = i.id_category,
filled = i.filled, id_filler = i.id_filler, id_torrent = i.id_torrent,
id_user = i.id_user, id_tgroup = i.id_tgroup, id_category = i.id_category,
id_release_type = i.id_release_type, year = i.year,
last_vote = i.last_vote, filled = i.filled, created = i.created,
modified = i.updated, description = i.description, title = i.title,
image = i.image, catalogue_number = i.catalogue_number,
record_label = i.record_label, log_score = i.log_score, need_log = i.need_log,
last_vote = i.last_vote, created = i.created, modified = i.updated,
description = i.description, title = i.title, image = i.image,
catalogue_number = i.catalogue_number, record_label = i.record_label,
log_score = i.log_score, need_log = i.need_log,
need_cue = i.need_cue, need_checksum = i.need_checksum,
encoding_str = string_to_array(i.encoding::text, '|'),
format_str = string_to_array(i.format::text, '|'),
media_str = string_to_array(i.media::text, '|'),
artist_title_ts = i.artist_title_ts,
tag = i.tag
artist_title_ts = i.artist_title_ts, tag = i.tag,
encoding_str = string_to_array(i.encoding_str::text, '|'),
format_str = string_to_array(i.format_str::text, '|'),
media_str = string_to_array(i.media_str::text, '|')
");
}
}

View File

@@ -135,7 +135,8 @@ class Request extends BaseObject implements CategoryHasArtist {
r.BitrateList AS encoding_list,
r.FormatList AS format_list,
r.MediaList AS media_list,
r.OCLC AS oclc
r.OCLC AS oclc,
r.updated AS modified
FROM requests r
INNER JOIN category c ON (c.category_id = r.CategoryID)
LEFT JOIN release_type rel ON (rel.ID = r.ReleaseType)
@@ -364,6 +365,10 @@ class Request extends BaseObject implements CategoryHasArtist {
return $this->info()['media_list'];
}
public function modified(): string {
return $this->info()['modified'];
}
public function logCue(): Request\LogCue {
return $this->info()['logCue'];
}

View File

@@ -34,6 +34,10 @@ abstract class AbstractValue {
return $this->all() || array_search($value, $this->label) !== false;
}
public function dbList(): array {
return array_values($this->label);
}
public function dbValue(): string {
return $this->all || count($this->label) == count($this->legal())
? 'Any'

View File

@@ -81,13 +81,26 @@ $db->prepared_query("
WHERE um.ID IS NULL
");
$userMan = new Manager\User();
$collageMan = new Manager\Collage();
$collageMan->requestContext()->setViewer(
$userMan->findById(
(int)$db->scalar('
SELECT um.id
FROM users_main um
INNER JOIN permissions p on (p.ID = um.PermissionID)
ORDER BY p.level DESC
LIMIT 1
')
)
);
// clean collages
$db->prepared_query("
SELECT ID
FROM collages
WHERE Name regexp '^(phpunit collage (?:ajax|artist|comment|contrib|personal|report) )'
");
$collageMan = new Manager\Collage();
foreach ($db->collect(0) as $collageId) {
$collage = $collageMan->findById($collageId);
echo "collage {$collage->id()} ({$collage->name()})\n";
@@ -148,23 +161,11 @@ foreach ($torrentList as $torrentId) {
$torrent->removeTorrent(null, 'garbage collection', -1);
}
}
$userMan = new Manager\User();
$tgMan = new Manager\TGroup();
$tgMan->requestContext()->setViewer(
$userMan->findById(
(int)$db->scalar('
SELECT um.id
FROM users_main um
INNER JOIN permissions p on (p.ID = um.PermissionID)
ORDER BY p.level DESC
LIMIT 1
')
)
);
$tgMan = new Manager\TGroup();
foreach ($groupList as $tgroupId) {
$tgroup = $tgMan->findById($tgroupId);
if ($tgroup) {
if ($tgroup instanceof TGroup) {
echo "tgroup $torrentId ({$tgroup->name()})\n";
$tgroup->remove(new User(1));
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class RequestVoteSummary extends AbstractMigration {
public function up(): void {
$this->query("
alter table request_vote add foreign key (id_request)
references request on delete cascade
");
$this->query("
create table request_vote_summary (
id_request int not null primary key
references request on delete cascade,
bounty bigint not null
)
");
$this->query("
insert into request_vote_summary (id_request, bounty)
select r.id_request, coalesce(sum(rv.bounty)::bigint, 0::bigint)
from request r
left join request_vote rv using (id_request)
group by r.id_request
");
$this->query("
create index rvs_b_idx on request_vote_summary (bounty)
");
}
public function down(): void {
$this->query("alter table request_vote drop constraint request_vote_id_request_fkey");
$this->table("request_vote_summary")->drop()->save();
}
}

View File

@@ -573,7 +573,7 @@ class DbTest extends TestCase {
public function testPgWrite(): void {
$this->expectException(\PDOException::class);
$this->expectExceptionMessageMatches(
'/^SQLSTATE\[\d+\]: Insufficient privilege: \d+ ERROR: permission denied for table counter$/'
'/^SQLSTATE\[\d+\]: Insufficient privilege: \d+ ERROR: permission denied for table counter/'
);
$this->pgro()->prepared_query("
insert into counter values ('phpunit-testWrite', 'fail on insert', 0)

View File

@@ -807,7 +807,6 @@ class RequestTest extends TestCase {
$this->request = Helper::makeRequestMusic($user, $title);
$artistName = 'artist ftsreq ' . randomString();
$this->request->artistRole()->set([ARTIST_MAIN => [$artistName]], $user);
new Manager\Request()->relay();
$this->assertEquals(
$this->request->id,