Optimize ReportedWeapon queries on user seasons page
Some checks failed
E2E Tests / e2e (push) Has been cancelled
Tests and checks on push / run-checks-and-tests (push) Has been cancelled
Updates translation progress / update-translation-progress-issue (push) Has been cancelled

This commit is contained in:
Kalle 2026-05-14 22:03:37 +03:00
parent 4bc8033841
commit d004efa3b1
16 changed files with 98 additions and 19 deletions

View File

@ -452,6 +452,7 @@ export interface ReportedWeapon {
mapIndex: number;
userId: number;
weaponSplId: MainWeaponId;
createdAt: Generated<number>;
}
export interface Skill {

View File

@ -112,9 +112,11 @@ export async function upsertOneTournament({
mapIndex,
userId,
weaponSplId,
createdAt,
}: TablesInsertable["ReportedWeapon"] & {
tournamentMatchId: number;
mapIndex: number;
createdAt: number;
}) {
await db
.deleteFrom("ReportedWeapon")
@ -125,7 +127,7 @@ export async function upsertOneTournament({
await db
.insertInto("ReportedWeapon")
.values({ tournamentMatchId, mapIndex, userId, weaponSplId })
.values({ tournamentMatchId, mapIndex, userId, weaponSplId, createdAt })
.execute();
}
@ -197,14 +199,14 @@ export async function seasonReportedWeaponsByUserId({
const sendouqWeapons = db
.selectFrom("ReportedWeapon")
.innerJoin("GroupMatch", "GroupMatch.id", "ReportedWeapon.groupMatchId")
.select(({ fn }) => [
"ReportedWeapon.weaponSplId",
fn.countAll<number>().as("count"),
])
.where("ReportedWeapon.userId", "=", userId)
.where("GroupMatch.createdAt", ">=", startsTs)
.where("GroupMatch.createdAt", "<=", endsTs)
.where("ReportedWeapon.groupMatchId", "is not", null)
.where("ReportedWeapon.createdAt", ">=", startsTs)
.where("ReportedWeapon.createdAt", "<=", endsTs)
.groupBy("ReportedWeapon.weaponSplId");
const tournamentWeapons = db
@ -220,27 +222,14 @@ export async function seasonReportedWeaponsByUserId({
"TournamentMatch.stageId",
)
.innerJoin("Tournament", "Tournament.id", "TournamentStage.tournamentId")
.innerJoin("CalendarEvent", "CalendarEvent.tournamentId", "Tournament.id")
.innerJoin(
(eb) =>
eb
.selectFrom("CalendarEventDate")
.select(({ fn }) => [
"CalendarEventDate.eventId",
fn.min("CalendarEventDate.startTime").as("startTime"),
])
.groupBy("CalendarEventDate.eventId")
.as("EventStartTime"),
(join) => join.onRef("EventStartTime.eventId", "=", "CalendarEvent.id"),
)
.select(({ fn }) => [
"ReportedWeapon.weaponSplId",
fn.countAll<number>().as("count"),
])
.where("ReportedWeapon.userId", "=", userId)
.where("Tournament.isFinalized", "=", 1)
.where("EventStartTime.startTime", ">=", startsTs)
.where("EventStartTime.startTime", "<=", endsTs)
.where("ReportedWeapon.createdAt", ">=", startsTs)
.where("ReportedWeapon.createdAt", "<=", endsTs)
.groupBy("ReportedWeapon.weaponSplId");
const rows = await db

View File

@ -24,6 +24,7 @@ import {
tournamentWebsocketRoom,
} from "~/features/tournament-bracket/tournament-bracket-utils";
import * as TournamentMatchRepository from "~/features/tournament-match/TournamentMatchRepository.server";
import { dateToDatabaseTimestamp } from "~/utils/dates";
import invariant from "~/utils/invariant";
import { logger } from "~/utils/logger";
import {
@ -784,6 +785,7 @@ export const action: ActionFunction = async ({ params, request }) => {
mapIndex: data.mapIndex,
userId: user.id,
weaponSplId: data.weaponSplId,
createdAt: dateToDatabaseTimestamp(tournament.ctx.startTime),
});
break;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,87 @@
export function up(db) {
db.pragma("foreign_keys = OFF");
db.transaction(() => {
db.prepare(
/* sql */ `
create table "ReportedWeapon_new" (
"groupMatchId" integer,
"tournamentMatchId" integer,
"mapIndex" integer not null,
"weaponSplId" integer not null,
"userId" integer not null,
"createdAt" integer default (strftime('%s', 'now')) not null,
foreign key ("groupMatchId") references "GroupMatch"("id") on delete cascade,
foreign key ("tournamentMatchId") references "TournamentMatch"("id") on delete cascade,
foreign key ("userId") references "User"("id") on delete restrict,
unique("groupMatchId", "mapIndex", "userId") on conflict rollback,
unique("tournamentMatchId", "mapIndex", "userId") on conflict rollback,
check (("groupMatchId" is not null) <> ("tournamentMatchId" is not null))
) strict
`,
).run();
db.prepare(
/* sql */ `
insert into "ReportedWeapon_new"
("groupMatchId", "tournamentMatchId", "mapIndex", "weaponSplId", "userId", "createdAt")
select
"rw"."groupMatchId",
"rw"."tournamentMatchId",
"rw"."mapIndex",
"rw"."weaponSplId",
"rw"."userId",
case
when "rw"."groupMatchId" is not null then (
select "GroupMatch"."createdAt"
from "GroupMatch"
where "GroupMatch"."id" = "rw"."groupMatchId"
)
else coalesce(
(
select min("CalendarEventDate"."startTime")
from "CalendarEventDate"
inner join "CalendarEvent"
on "CalendarEvent"."id" = "CalendarEventDate"."eventId"
inner join "Tournament"
on "Tournament"."id" = "CalendarEvent"."tournamentId"
inner join "TournamentStage"
on "TournamentStage"."tournamentId" = "Tournament"."id"
inner join "TournamentMatch"
on "TournamentMatch"."stageId" = "TournamentStage"."id"
where "TournamentMatch"."id" = "rw"."tournamentMatchId"
),
strftime('%s', 'now')
)
end
from "ReportedWeapon" as "rw"
`,
).run();
db.prepare(/* sql */ `drop table "ReportedWeapon"`).run();
db.prepare(
/* sql */ `alter table "ReportedWeapon_new" rename to "ReportedWeapon"`,
).run();
db.prepare(
/* sql */ `create index reported_weapon_group_match_id on "ReportedWeapon"("groupMatchId")`,
).run();
db.prepare(
/* sql */ `create index reported_weapon_tournament_match_id on "ReportedWeapon"("tournamentMatchId")`,
).run();
db.prepare(
/* sql */ `create index reported_weapon_user_id on "ReportedWeapon"("userId")`,
).run();
db.prepare(
/* sql */ `create index reported_weapon_user_created_at_weapon on "ReportedWeapon"("userId", "createdAt", "weaponSplId")`,
).run();
db.pragma("foreign_key_check");
})();
db.pragma("foreign_keys = ON");
}