mirror of
https://github.com/OPSnet/Gazelle.git
synced 2026-01-16 18:04:34 -05:00
add request_vote_summary table for ordering searches
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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, '|')
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'];
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
36
misc/pg-migrations/20250610000000_request_vote_summary.php
Normal file
36
misc/pg-migrations/20250610000000_request_vote_summary.php
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user