From 8da1c9292391a39b8c08ed9f7cd7a2bb10217588 Mon Sep 17 00:00:00 2001 From: fallenbagel <98979876+fallenbagel@users.noreply.github.com> Date: Sat, 10 May 2025 03:38:22 +0800 Subject: [PATCH] fix(entity): use TIMESTAMPTZ in Postgres and sort issue comments oldest-first (#1654) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(entity): use TIMESTAMPTZ in Postgres and sort issue comments oldest-first Switch key datetime columns to TIMESTAMPTZ for proper UTC handling (“just now”) and sort issue comments on load so the original description stays first and in proper sorted order in fix-pgsql-timezone fixes #1569, fixes #1568 * refactor(migration): manually rewrite pgsql migration to preserve existing data Typeorm generated migration was dropping the entire column thus leading to data loss so this is an attempt at manually rewriting the migration to preserve the data * refactor(migrations): rename to be consistent with other migration files * fix: use id to order instead of createdAt to avoid non-existant createdAt --------- Co-authored-by: Gauthier --- server/entity/Blacklist.ts | 4 +- server/entity/DiscoverSlider.ts | 17 +- server/entity/Issue.ts | 17 +- server/entity/IssueComment.ts | 18 +- server/entity/Media.ts | 10 +- server/entity/MediaRequest.ts | 11 +- server/entity/OverrideRule.ts | 17 +- server/entity/Season.ts | 18 +- server/entity/SeasonRequest.ts | 18 +- server/entity/User.ts | 11 +- server/entity/UserPushSubscription.ts | 15 +- server/entity/Watchlist.ts | 11 +- .../1746811308203-FixIssueTimestamps.ts | 231 ++++++++++++++++++ 13 files changed, 320 insertions(+), 78 deletions(-) create mode 100644 server/migration/postgres/1746811308203-FixIssueTimestamps.ts diff --git a/server/entity/Blacklist.ts b/server/entity/Blacklist.ts index a6bac9d9e..64c44e50d 100644 --- a/server/entity/Blacklist.ts +++ b/server/entity/Blacklist.ts @@ -3,10 +3,10 @@ import dataSource from '@server/datasource'; import Media from '@server/entity/Media'; import { User } from '@server/entity/User'; import type { BlacklistItem } from '@server/interfaces/api/blacklistInterfaces'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; import type { EntityManager } from 'typeorm'; import { Column, - CreateDateColumn, Entity, Index, JoinColumn, @@ -47,7 +47,7 @@ export class Blacklist implements BlacklistItem { @Column({ nullable: true, type: 'varchar' }) public blacklistedTags?: string; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; constructor(init?: Partial) { diff --git a/server/entity/DiscoverSlider.ts b/server/entity/DiscoverSlider.ts index 261419a07..0de0aef81 100644 --- a/server/entity/DiscoverSlider.ts +++ b/server/entity/DiscoverSlider.ts @@ -2,13 +2,8 @@ import type { DiscoverSliderType } from '@server/constants/discover'; import { defaultSliders } from '@server/constants/discover'; import { getRepository } from '@server/datasource'; import logger from '@server/logger'; -import { - Column, - CreateDateColumn, - Entity, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; @Entity() class DiscoverSlider { @@ -55,10 +50,14 @@ class DiscoverSlider { @Column({ nullable: true }) public data?: string; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; constructor(init?: Partial) { diff --git a/server/entity/Issue.ts b/server/entity/Issue.ts index fae96967d..8ff88e3b7 100644 --- a/server/entity/Issue.ts +++ b/server/entity/Issue.ts @@ -1,13 +1,13 @@ import type { IssueType } from '@server/constants/issue'; import { IssueStatus } from '@server/constants/issue'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; import { + AfterLoad, Column, - CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, - UpdateDateColumn, } from 'typeorm'; import IssueComment from './IssueComment'; import Media from './Media'; @@ -55,12 +55,21 @@ class Issue { }) public comments: IssueComment[]; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; + @AfterLoad() + sortComments() { + this.comments?.sort((a, b) => a.id - b.id); + } + constructor(init?: Partial) { Object.assign(this, init); } diff --git a/server/entity/IssueComment.ts b/server/entity/IssueComment.ts index e45216392..c36b3746c 100644 --- a/server/entity/IssueComment.ts +++ b/server/entity/IssueComment.ts @@ -1,11 +1,5 @@ -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import Issue from './Issue'; import { User } from './User'; @@ -28,10 +22,14 @@ class IssueComment { @Column({ type: 'text' }) public message: string; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; constructor(init?: Partial) { diff --git a/server/entity/Media.ts b/server/entity/Media.ts index 33155a1ff..38726f701 100644 --- a/server/entity/Media.ts +++ b/server/entity/Media.ts @@ -15,13 +15,11 @@ import { getHostname } from '@server/utils/getHostname'; import { AfterLoad, Column, - CreateDateColumn, Entity, Index, OneToMany, OneToOne, PrimaryGeneratedColumn, - UpdateDateColumn, } from 'typeorm'; import Issue from './Issue'; import { MediaRequest } from './MediaRequest'; @@ -128,10 +126,14 @@ class Media { @OneToOne(() => Blacklist, (blacklist) => blacklist.media) public blacklist: Promise; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; /** diff --git a/server/entity/MediaRequest.ts b/server/entity/MediaRequest.ts index cd103ef4f..e5dabc241 100644 --- a/server/entity/MediaRequest.ts +++ b/server/entity/MediaRequest.ts @@ -13,18 +13,17 @@ import notificationManager, { Notification } from '@server/lib/notifications'; import { Permission } from '@server/lib/permissions'; import { getSettings } from '@server/lib/settings'; import logger from '@server/logger'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; import { truncate } from 'lodash'; import { AfterInsert, AfterUpdate, Column, - CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, RelationCount, - UpdateDateColumn, } from 'typeorm'; import Media from './Media'; import SeasonRequest from './SeasonRequest'; @@ -535,10 +534,14 @@ export class MediaRequest { }) public modifiedBy?: User; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; @Column({ type: 'varchar' }) diff --git a/server/entity/OverrideRule.ts b/server/entity/OverrideRule.ts index bf1373438..aab72006f 100644 --- a/server/entity/OverrideRule.ts +++ b/server/entity/OverrideRule.ts @@ -1,10 +1,5 @@ -import { - Column, - CreateDateColumn, - Entity, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; @Entity() class OverrideRule { @@ -38,10 +33,14 @@ class OverrideRule { @Column({ nullable: true }) public tags?: string; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; constructor(init?: Partial) { diff --git a/server/entity/Season.ts b/server/entity/Season.ts index d488a5c19..7d38581ed 100644 --- a/server/entity/Season.ts +++ b/server/entity/Season.ts @@ -1,12 +1,6 @@ import { MediaStatus } from '@server/constants/media'; -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import Media from './Media'; @Entity() @@ -28,10 +22,14 @@ class Season { }) public media: Promise; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; constructor(init?: Partial) { diff --git a/server/entity/SeasonRequest.ts b/server/entity/SeasonRequest.ts index f9eeef501..9262877b8 100644 --- a/server/entity/SeasonRequest.ts +++ b/server/entity/SeasonRequest.ts @@ -1,12 +1,6 @@ import { MediaRequestStatus } from '@server/constants/media'; -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { MediaRequest } from './MediaRequest'; @Entity() @@ -25,10 +19,14 @@ class SeasonRequest { }) public request: MediaRequest; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; constructor(init?: Partial) { diff --git a/server/entity/User.ts b/server/entity/User.ts index 5f51af710..8a96f396e 100644 --- a/server/entity/User.ts +++ b/server/entity/User.ts @@ -9,6 +9,7 @@ import { hasPermission, Permission } from '@server/lib/permissions'; import { getSettings } from '@server/lib/settings'; import logger from '@server/logger'; import { AfterDate } from '@server/utils/dateHelpers'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; import bcrypt from 'bcrypt'; import { randomUUID } from 'crypto'; import path from 'path'; @@ -16,14 +17,12 @@ import { default as generatePassword } from 'secure-random-password'; import { AfterLoad, Column, - CreateDateColumn, Entity, Not, OneToMany, OneToOne, PrimaryGeneratedColumn, RelationCount, - UpdateDateColumn, } from 'typeorm'; import Issue from './Issue'; import { MediaRequest } from './MediaRequest'; @@ -138,10 +137,14 @@ export class User { @OneToMany(() => Issue, (issue) => issue.createdBy, { cascade: true }) public createdIssues: Issue[]; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; public warnings: string[] = []; diff --git a/server/entity/UserPushSubscription.ts b/server/entity/UserPushSubscription.ts index f05dd0f2b..b3c4d5d2b 100644 --- a/server/entity/UserPushSubscription.ts +++ b/server/entity/UserPushSubscription.ts @@ -1,10 +1,5 @@ -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryGeneratedColumn, -} from 'typeorm'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { User } from './User'; @Entity() @@ -30,7 +25,11 @@ export class UserPushSubscription { @Column({ nullable: true }) public userAgent: string; - @CreateDateColumn({ nullable: true }) + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + nullable: true, + }) public createdAt: Date; constructor(init?: Partial) { diff --git a/server/entity/Watchlist.ts b/server/entity/Watchlist.ts index df820120e..10c26246a 100644 --- a/server/entity/Watchlist.ts +++ b/server/entity/Watchlist.ts @@ -5,15 +5,14 @@ import Media from '@server/entity/Media'; import { User } from '@server/entity/User'; import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces'; import logger from '@server/logger'; +import { DbAwareColumn } from '@server/utils/DbColumnHelper'; import { Column, - CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, Unique, - UpdateDateColumn, } from 'typeorm'; import type { ZodNumber, ZodOptional, ZodString } from 'zod'; @@ -56,10 +55,14 @@ export class Watchlist implements WatchlistItem { }) public media: Media; - @CreateDateColumn() + @DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public createdAt: Date; - @UpdateDateColumn() + @DbAwareColumn({ + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + onUpdate: 'CURRENT_TIMESTAMP', + }) public updatedAt: Date; constructor(init?: Partial) { diff --git a/server/migration/postgres/1746811308203-FixIssueTimestamps.ts b/server/migration/postgres/1746811308203-FixIssueTimestamps.ts new file mode 100644 index 000000000..ac0bae3a8 --- /dev/null +++ b/server/migration/postgres/1746811308203-FixIssueTimestamps.ts @@ -0,0 +1,231 @@ +import type { MigrationInterface, QueryRunner } from 'typeorm'; + +export class FixIssueTimestamps1746811308203 implements MigrationInterface { + name = 'FixIssueTimestamps1746811308203'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "watchlist" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "watchlist" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "override_rule" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "override_rule" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season_request" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season_request" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media_request" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media_request" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "user_push_subscription" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "blacklist" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue_comment" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue_comment" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "discover_slider" + ALTER COLUMN "createdAt" TYPE TIMESTAMP WITH TIME ZONE + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "discover_slider" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP WITH TIME ZONE + USING "updatedAt" AT TIME ZONE 'UTC' + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "discover_slider" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "discover_slider" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue_comment" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue_comment" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "issue" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "blacklist" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "user_push_subscription" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media_request" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "media_request" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season_request" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "season_request" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "override_rule" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "override_rule" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "watchlist" + ALTER COLUMN "updatedAt" TYPE TIMESTAMP + USING "updatedAt" AT TIME ZONE 'UTC' + `); + await queryRunner.query(` + ALTER TABLE "watchlist" + ALTER COLUMN "createdAt" TYPE TIMESTAMP + USING "createdAt" AT TIME ZONE 'UTC' + `); + } +}