Use ids as pk for infos

This commit is contained in:
Zoe Roux 2026-04-13 10:28:02 +02:00
parent 8fb15e6a34
commit fbb995a3a6
No known key found for this signature in database
5 changed files with 147 additions and 37 deletions

View File

@ -0,0 +1,49 @@
begin;
-- chapters
alter table gocoder.chapters add column sha varchar(40);
update gocoder.chapters c set sha = i.sha from gocoder.info i where c.id = i.id;
alter table gocoder.chapters alter column sha set not null;
alter table gocoder.chapters drop constraint chapter_pk;
alter table gocoder.chapters drop constraint chapters_info_fk;
alter table gocoder.chapters drop column id;
alter table gocoder.chapters add constraint chapter_pk primary key (sha, start_time);
alter table gocoder.chapters add foreign key (sha) references gocoder.info(sha) on delete cascade;
-- subtitles
alter table gocoder.subtitles add column sha varchar(40);
update gocoder.subtitles s set sha = i.sha from gocoder.info i where s.id = i.id;
alter table gocoder.subtitles alter column sha set not null;
alter table gocoder.subtitles drop constraint subtitle_pk;
alter table gocoder.subtitles drop constraint subtitles_info_fk;
alter table gocoder.subtitles drop column id;
alter table gocoder.subtitles add constraint subtitle_pk primary key (sha, idx);
alter table gocoder.subtitles add foreign key (sha) references gocoder.info(sha) on delete cascade;
-- audios
alter table gocoder.audios add column sha varchar(40);
update gocoder.audios a set sha = i.sha from gocoder.info i where a.id = i.id;
alter table gocoder.audios alter column sha set not null;
alter table gocoder.audios drop constraint audios_pk;
alter table gocoder.audios drop constraint audios_info_fk;
alter table gocoder.audios drop column id;
alter table gocoder.audios add constraint audios_pk primary key (sha, idx);
alter table gocoder.audios add foreign key (sha) references gocoder.info(sha) on delete cascade;
-- videos
alter table gocoder.videos add column sha varchar(40);
update gocoder.videos v set sha = i.sha from gocoder.info i where v.id = i.id;
alter table gocoder.videos alter column sha set not null;
alter table gocoder.videos drop constraint videos_pk;
alter table gocoder.videos drop constraint videos_info_fk;
alter table gocoder.videos drop column id;
alter table gocoder.videos add constraint videos_pk primary key (sha, idx);
alter table gocoder.videos add foreign key (sha) references gocoder.info(sha) on delete cascade;
alter table gocoder.info drop column id;
commit;

View File

@ -0,0 +1,55 @@
begin;
alter table gocoder.info add column id serial unique not null;
alter table gocoder.info drop constraint info_pkey;
alter table gocoder.info add constraint info_pkey primary key(id);
-- videos
alter table gocoder.videos add column id integer;
update gocoder.videos v set id = i.id from gocoder.info i where v.sha = i.sha;
alter table gocoder.videos alter column id set not null;
alter table gocoder.videos drop constraint videos_pk;
alter table gocoder.videos drop constraint videos_sha_fkey;
alter table gocoder.videos drop column sha;
alter table gocoder.videos add constraint videos_info_fk
foreign key (id) references gocoder.info(id) on delete cascade;
alter table gocoder.videos add constraint videos_pk primary key (id, idx);
-- audios
alter table gocoder.audios add column id integer;
update gocoder.audios a set id = i.id from gocoder.info i where a.sha = i.sha;
alter table gocoder.audios alter column id set not null;
alter table gocoder.audios drop constraint audios_pk;
alter table gocoder.audios drop constraint audios_sha_fkey;
alter table gocoder.audios drop column sha;
alter table gocoder.audios add constraint audios_info_fk
foreign key (id) references gocoder.info(id) on delete cascade;
alter table gocoder.audios add constraint audios_pk primary key (id, idx);
-- subtitles
alter table gocoder.subtitles add column id integer;
update gocoder.subtitles s set id = i.id from gocoder.info i where s.sha = i.sha;
alter table gocoder.subtitles alter column id set not null;
alter table gocoder.subtitles drop constraint subtitle_pk;
alter table gocoder.subtitles drop constraint subtitles_sha_fkey;
alter table gocoder.subtitles drop column sha;
alter table gocoder.subtitles add constraint subtitles_info_fk
foreign key (id) references gocoder.info(id) on delete cascade;
alter table gocoder.subtitles add constraint subtitle_pk primary key (id, idx);
-- chapters
alter table gocoder.chapters add column id integer;
update gocoder.chapters c set id = i.id from gocoder.info i where c.sha = i.sha;
alter table gocoder.chapters alter column id set not null;
alter table gocoder.chapters drop constraint chapter_pk;
alter table gocoder.chapters drop constraint chapters_sha_fkey;
alter table gocoder.chapters drop column sha;
alter table gocoder.chapters add constraint chapters_info_fk
foreign key (id) references gocoder.info(id) on delete cascade;
alter table gocoder.chapters add constraint chapter_pk primary key (id, start_time);
commit;

View File

@ -27,6 +27,8 @@ type Versions struct {
}
type MediaInfo struct {
// Auto-increment id used as foreign key for related tables.
Id int32 `json:"id" db:"id"`
// The sha1 of the video file.
Sha string `json:"sha" db:"sha"`
/// The internal path of the video file.
@ -60,7 +62,7 @@ type MediaInfo struct {
}
type Video struct {
Sha string `json:"-" db:"sha"`
Id int32 `json:"-" db:"id"`
/// The index of this track on the media.
Index uint32 `json:"index" db:"idx"`
@ -86,7 +88,7 @@ type Video struct {
}
type Audio struct {
Sha string `json:"-" db:"sha"`
Id int32 `json:"-" db:"id"`
/// The index of this track on the media.
Index uint32 `json:"index" db:"idx"`
@ -110,7 +112,7 @@ type Audio struct {
}
type Subtitle struct {
Sha string `json:"-" db:"sha"`
Id int32 `json:"-" db:"id"`
/// The index of this track on the media.
Index *uint32 `json:"index" db:"idx"`
@ -137,7 +139,7 @@ type Subtitle struct {
}
type Chapter struct {
Sha string `json:"-" db:"sha"`
Id int32 `json:"-" db:"id"`
/// The start time of the chapter (in second from the start of the episode).
StartTime float32 `json:"startTime" db:"start_time"`

View File

@ -160,12 +160,12 @@ func (s *MetadataService) GetKeyframes(info *MediaInfo, isVideo bool, idx uint32
tx, _ := s.Database.Begin(ctx)
tx.Exec(
ctx,
fmt.Sprintf(`update %s set keyframes = $3 where sha = $1 and idx = $2`, table),
info.Sha,
fmt.Sprintf(`update %s set keyframes = $3 where id = $1 and idx = $2`, table),
info.Id,
idx,
kf.Keyframes,
)
tx.Exec(ctx, `update gocoder.info set ver_keyframes = $2 where sha = $1`, info.Sha, KeyframeVersion)
tx.Exec(ctx, `update gocoder.info set ver_keyframes = $2 where id = $1`, info.Id, KeyframeVersion)
err = tx.Commit(ctx)
if err != nil {
log.Printf("Couldn't store keyframes on database: %v", err)

View File

@ -171,9 +171,9 @@ func (s *MetadataService) GetMetadata(ctx context.Context, path string, sha stri
if err != nil {
return nil, err
}
tx.Exec(bgCtx, `update gocoder.videos set keyframes = null where sha = $1`, sha)
tx.Exec(bgCtx, `update gocoder.audios set keyframes = null where sha = $1`, sha)
tx.Exec(bgCtx, `update gocoder.info set ver_keyframes = 0 where sha = $1`, sha)
tx.Exec(bgCtx, `update gocoder.videos set keyframes = null where id = $1`, ret.Id)
tx.Exec(bgCtx, `update gocoder.audios set keyframes = null where id = $1`, ret.Id)
tx.Exec(bgCtx, `update gocoder.info set ver_keyframes = 0 where id = $1`, ret.Id)
err = tx.Commit(bgCtx)
if err != nil {
fmt.Printf("error deleting old keyframes from database: %v", err)
@ -187,7 +187,7 @@ func (s *MetadataService) getMetadata(ctx context.Context, path string, sha stri
rows, _ := s.Database.Query(
ctx,
`select
i.sha, i.path, i.extension, i.mime_codec, i.size, i.duration, i.container, i.fonts,
i.id, i.sha, i.path, i.extension, i.mime_codec, i.size, i.duration, i.container, i.fonts,
jsonb_build_object(
'info', i.ver_info,
'extract', i.ver_extract,
@ -209,8 +209,8 @@ func (s *MetadataService) getMetadata(ctx context.Context, path string, sha stri
rows, _ = s.Database.Query(
ctx,
`select * from gocoder.videos as v where v.sha=$1`,
sha,
`select * from gocoder.videos as v where v.id=$1`,
ret.Id,
)
ret.Videos, err = pgx.CollectRows(rows, pgx.RowToStructByName[Video])
if err != nil {
@ -219,8 +219,8 @@ func (s *MetadataService) getMetadata(ctx context.Context, path string, sha stri
rows, _ = s.Database.Query(
ctx,
`select * from gocoder.audios as a where a.sha=$1`,
sha,
`select * from gocoder.audios as a where a.id=$1`,
ret.Id,
)
ret.Audios, err = pgx.CollectRows(rows, pgx.RowToStructByName[Audio])
if err != nil {
@ -229,8 +229,8 @@ func (s *MetadataService) getMetadata(ctx context.Context, path string, sha stri
rows, _ = s.Database.Query(
ctx,
`select * from gocoder.subtitles as s where s.sha=$1`,
sha,
`select * from gocoder.subtitles as s where s.id=$1`,
ret.Id,
)
ret.Subtitles, err = pgx.CollectRows(rows, pgx.RowToStructByName[Subtitle])
if err != nil {
@ -254,8 +254,8 @@ func (s *MetadataService) getMetadata(ctx context.Context, path string, sha stri
rows, _ = s.Database.Query(
ctx,
`select * from gocoder.chapters as c where c.sha=$1`,
sha,
`select * from gocoder.chapters as c where c.id=$1`,
ret.Id,
)
ret.Chapters, err = pgx.CollectRows(rows, pgx.RowToStructByName[Chapter])
if err != nil {
@ -283,24 +283,28 @@ func (s *MetadataService) storeFreshMetadata(ctx context.Context, path string, s
// it needs to be a delete instead of a on conflict do update because we want to trigger delete casquade for
// videos/audios & co.
tx.Exec(ctx, `delete from gocoder.info where path = $1`, path)
tx.Exec(ctx,
err = tx.QueryRow(ctx,
`
insert into gocoder.info(sha, path, extension, mime_codec, size, duration, container,
fonts, ver_info, ver_extract, ver_thumbs, ver_keyframes)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
returning id
`,
// on conflict do not update versions of extract/thumbs/keyframes
ret.Sha, ret.Path, ret.Extension, ret.MimeCodec, ret.Size, ret.Duration, ret.Container,
ret.Fonts, ret.Versions.Info, ret.Versions.Extract, ret.Versions.Thumbs, ret.Versions.Keyframes,
)
).Scan(&ret.Id)
if err != nil {
return set(ret, fmt.Errorf("failed to insert info: %w", err))
}
for _, v := range ret.Videos {
tx.Exec(
ctx,
`
insert into gocoder.videos(sha, idx, title, language, codec, mime_codec, width, height, is_default, bitrate)
insert into gocoder.videos(id, idx, title, language, codec, mime_codec, width, height, is_default, bitrate)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
on conflict (sha, idx) do update set
sha = excluded.sha,
on conflict (id, idx) do update set
id = excluded.id,
idx = excluded.idx,
title = excluded.title,
language = excluded.language,
@ -311,17 +315,17 @@ func (s *MetadataService) storeFreshMetadata(ctx context.Context, path string, s
is_default = excluded.is_default,
bitrate = excluded.bitrate
`,
ret.Sha, v.Index, v.Title, v.Language, v.Codec, v.MimeCodec, v.Width, v.Height, v.IsDefault, v.Bitrate,
ret.Id, v.Index, v.Title, v.Language, v.Codec, v.MimeCodec, v.Width, v.Height, v.IsDefault, v.Bitrate,
)
}
for _, a := range ret.Audios {
tx.Exec(
ctx,
`
insert into gocoder.audios(sha, idx, title, language, codec, mime_codec, channels, is_default, bitrate)
insert into gocoder.audios(id, idx, title, language, codec, mime_codec, channels, is_default, bitrate)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
on conflict (sha, idx) do update set
sha = excluded.sha,
on conflict (id, idx) do update set
id = excluded.id,
idx = excluded.idx,
title = excluded.title,
language = excluded.language,
@ -331,17 +335,17 @@ func (s *MetadataService) storeFreshMetadata(ctx context.Context, path string, s
is_default = excluded.is_default,
bitrate = excluded.bitrate
`,
ret.Sha, a.Index, a.Title, a.Language, a.Codec, a.MimeCodec, a.Channels, a.IsDefault, a.Bitrate,
ret.Id, a.Index, a.Title, a.Language, a.Codec, a.MimeCodec, a.Channels, a.IsDefault, a.Bitrate,
)
}
for _, s := range ret.Subtitles {
tx.Exec(
ctx,
`
insert into gocoder.subtitles(sha, idx, title, language, codec, extension, is_default, is_forced, is_hearing_impaired)
insert into gocoder.subtitles(id, idx, title, language, codec, extension, is_default, is_forced, is_hearing_impaired)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
on conflict (sha, idx) do update set
sha = excluded.sha,
on conflict (id, idx) do update set
id = excluded.id,
idx = excluded.idx,
title = excluded.title,
language = excluded.language,
@ -351,23 +355,23 @@ func (s *MetadataService) storeFreshMetadata(ctx context.Context, path string, s
is_forced = excluded.is_forced,
is_hearing_impaired = excluded.is_hearing_impaired
`,
ret.Sha, s.Index, s.Title, s.Language, s.Codec, s.Extension, s.IsDefault, s.IsForced, s.IsHearingImpaired,
ret.Id, s.Index, s.Title, s.Language, s.Codec, s.Extension, s.IsDefault, s.IsForced, s.IsHearingImpaired,
)
}
for _, c := range ret.Chapters {
tx.Exec(
ctx,
`
insert into gocoder.chapters(sha, start_time, end_time, name, type)
insert into gocoder.chapters(id, start_time, end_time, name, type)
values ($1, $2, $3, $4, $5)
on conflict (sha, start_time) do update set
sha = excluded.sha,
on conflict (id, start_time) do update set
id = excluded.id,
start_time = excluded.start_time,
end_time = excluded.end_time,
name = excluded.name,
type = excluded.type
`,
ret.Sha, c.StartTime, c.EndTime, c.Name, c.Type,
ret.Id, c.StartTime, c.EndTime, c.Name, c.Type,
)
}
err = tx.Commit(ctx)