mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
[Files Refactor] Performance tuning (#2819)
* Load scene relationships on demand * Load image relationships on demand * Load gallery relationships on demand * Add dataloaden * Use dataloaders * Use where in for other find many functions
This commit is contained in:
@@ -133,14 +133,20 @@ func (qb *GalleryStore) Create(ctx context.Context, newObject *models.Gallery, f
|
||||
}
|
||||
}
|
||||
|
||||
if err := galleriesPerformersTableMgr.insertJoins(ctx, id, newObject.PerformerIDs); err != nil {
|
||||
return err
|
||||
if newObject.PerformerIDs.Loaded() {
|
||||
if err := galleriesPerformersTableMgr.insertJoins(ctx, id, newObject.PerformerIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := galleriesTagsTableMgr.insertJoins(ctx, id, newObject.TagIDs); err != nil {
|
||||
return err
|
||||
if newObject.TagIDs.Loaded() {
|
||||
if err := galleriesTagsTableMgr.insertJoins(ctx, id, newObject.TagIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := galleriesScenesTableMgr.insertJoins(ctx, id, newObject.SceneIDs); err != nil {
|
||||
return err
|
||||
if newObject.SceneIDs.Loaded() {
|
||||
if err := galleriesScenesTableMgr.insertJoins(ctx, id, newObject.SceneIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
updated, err := qb.Find(ctx, id)
|
||||
@@ -161,14 +167,20 @@ func (qb *GalleryStore) Update(ctx context.Context, updatedObject *models.Galler
|
||||
return err
|
||||
}
|
||||
|
||||
if err := galleriesPerformersTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.PerformerIDs); err != nil {
|
||||
return err
|
||||
if updatedObject.PerformerIDs.Loaded() {
|
||||
if err := galleriesPerformersTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.PerformerIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := galleriesTagsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.TagIDs); err != nil {
|
||||
return err
|
||||
if updatedObject.TagIDs.Loaded() {
|
||||
if err := galleriesTagsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.TagIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := galleriesScenesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.SceneIDs); err != nil {
|
||||
return err
|
||||
if updatedObject.SceneIDs.Loaded() {
|
||||
if err := galleriesScenesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.SceneIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fileIDs := make([]file.ID, len(updatedObject.Files))
|
||||
@@ -249,16 +261,18 @@ func (qb *GalleryStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*
|
||||
|
||||
s := f.resolve()
|
||||
|
||||
if err := qb.resolveRelationships(ctx, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, s)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, s := range ret {
|
||||
if err := qb.resolveRelationships(ctx, s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -281,24 +295,6 @@ func (qb *GalleryStore) resolveRelationships(ctx context.Context, s *models.Gall
|
||||
s.FolderPath = folder.Path
|
||||
}
|
||||
|
||||
// performers
|
||||
s.PerformerIDs, err = qb.performersRepository().getIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving gallery performers: %w", err)
|
||||
}
|
||||
|
||||
// tags
|
||||
s.TagIDs, err = qb.tagsRepository().getIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving gallery tags: %w", err)
|
||||
}
|
||||
|
||||
// scenes
|
||||
s.SceneIDs, err = qb.scenesRepository().getIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving gallery scenes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -989,6 +985,11 @@ func (qb *GalleryStore) filesRepository() *filesRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) AddFileID(ctx context.Context, id int, fileID file.ID) error {
|
||||
const firstPrimary = false
|
||||
return galleriesFilesTableMgr.insertJoins(ctx, id, firstPrimary, []file.ID{fileID})
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) performersRepository() *joinRepository {
|
||||
return &joinRepository{
|
||||
repository: repository{
|
||||
@@ -1000,6 +1001,10 @@ func (qb *GalleryStore) performersRepository() *joinRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) GetPerformerIDs(ctx context.Context, id int) ([]int, error) {
|
||||
return qb.performersRepository().getIDs(ctx, id)
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) tagsRepository() *joinRepository {
|
||||
return &joinRepository{
|
||||
repository: repository{
|
||||
@@ -1011,6 +1016,10 @@ func (qb *GalleryStore) tagsRepository() *joinRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) GetTagIDs(ctx context.Context, id int) ([]int, error) {
|
||||
return qb.tagsRepository().getIDs(ctx, id)
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) imagesRepository() *joinRepository {
|
||||
return &joinRepository{
|
||||
repository: repository{
|
||||
@@ -1041,3 +1050,7 @@ func (qb *GalleryStore) scenesRepository() *joinRepository {
|
||||
fkColumn: sceneIDColumn,
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *GalleryStore) GetSceneIDs(ctx context.Context, id int) ([]int, error) {
|
||||
return qb.scenesRepository().getIDs(ctx, id)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,26 @@ import (
|
||||
|
||||
var invalidID = -1
|
||||
|
||||
func loadGalleryRelationships(ctx context.Context, expected models.Gallery, actual *models.Gallery) error {
|
||||
if expected.SceneIDs.Loaded() {
|
||||
if err := actual.LoadSceneIDs(ctx, db.Gallery); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.TagIDs.Loaded() {
|
||||
if err := actual.LoadTagIDs(ctx, db.Gallery); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.PerformerIDs.Loaded() {
|
||||
if err := actual.LoadPerformerIDs(ctx, db.Gallery); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_galleryQueryBuilder_Create(t *testing.T) {
|
||||
var (
|
||||
title = "title"
|
||||
@@ -48,9 +68,9 @@ func Test_galleryQueryBuilder_Create(t *testing.T) {
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
SceneIDs: []int{sceneIDs[sceneIdx1WithPerformer], sceneIDs[sceneIdx1WithStudio]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
SceneIDs: models.NewRelatedIDs([]int{sceneIDs[sceneIdx1WithPerformer], sceneIDs[sceneIdx1WithStudio]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Files: []file.File{},
|
||||
},
|
||||
false,
|
||||
@@ -70,9 +90,9 @@ func Test_galleryQueryBuilder_Create(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
SceneIDs: []int{sceneIDs[sceneIdx1WithPerformer], sceneIDs[sceneIdx1WithStudio]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
SceneIDs: models.NewRelatedIDs([]int{sceneIDs[sceneIdx1WithPerformer], sceneIDs[sceneIdx1WithStudio]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -86,21 +106,21 @@ func Test_galleryQueryBuilder_Create(t *testing.T) {
|
||||
{
|
||||
"invalid scene id",
|
||||
models.Gallery{
|
||||
SceneIDs: []int{invalidID},
|
||||
SceneIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid tag id",
|
||||
models.Gallery{
|
||||
TagIDs: []int{invalidID},
|
||||
TagIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid performer id",
|
||||
models.Gallery{
|
||||
PerformerIDs: []int{invalidID},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -132,6 +152,12 @@ func Test_galleryQueryBuilder_Create(t *testing.T) {
|
||||
copy := tt.newObject
|
||||
copy.ID = s.ID
|
||||
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, copy, &s); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, s)
|
||||
|
||||
// ensure can find the scene
|
||||
@@ -144,6 +170,12 @@ func Test_galleryQueryBuilder_Create(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, copy, found); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, *found)
|
||||
|
||||
return
|
||||
@@ -190,9 +222,9 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
SceneIDs: []int{sceneIDs[sceneIdx1WithPerformer], sceneIDs[sceneIdx1WithStudio]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
SceneIDs: models.NewRelatedIDs([]int{sceneIDs[sceneIdx1WithPerformer], sceneIDs[sceneIdx1WithStudio]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -203,9 +235,9 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
Files: []file.File{
|
||||
makeGalleryFileWithID(galleryIdxWithImage),
|
||||
},
|
||||
SceneIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
SceneIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -219,9 +251,9 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
Files: []file.File{
|
||||
makeGalleryFileWithID(galleryIdxWithScene),
|
||||
},
|
||||
SceneIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
SceneIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -235,9 +267,9 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
Files: []file.File{
|
||||
makeGalleryFileWithID(galleryIdxWithTag),
|
||||
},
|
||||
SceneIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
SceneIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -251,9 +283,9 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
Files: []file.File{
|
||||
makeGalleryFileWithID(galleryIdxWithPerformer),
|
||||
},
|
||||
SceneIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
SceneIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -282,7 +314,7 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
makeGalleryFileWithID(galleryIdxWithImage),
|
||||
},
|
||||
Organized: true,
|
||||
SceneIDs: []int{invalidID},
|
||||
SceneIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
},
|
||||
@@ -296,7 +328,7 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
makeGalleryFileWithID(galleryIdxWithImage),
|
||||
},
|
||||
Organized: true,
|
||||
TagIDs: []int{invalidID},
|
||||
TagIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
},
|
||||
@@ -310,7 +342,7 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
makeGalleryFileWithID(galleryIdxWithImage),
|
||||
},
|
||||
Organized: true,
|
||||
PerformerIDs: []int{invalidID},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
},
|
||||
@@ -339,6 +371,12 @@ func Test_galleryQueryBuilder_Update(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, copy, s); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, *s)
|
||||
|
||||
return
|
||||
@@ -426,9 +464,9 @@ func Test_galleryQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
SceneIDs: []int{sceneIDs[sceneIdxWithGallery]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithGallery], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithGallery], performerIDs[performerIdx1WithDupName]},
|
||||
SceneIDs: models.NewRelatedIDs([]int{sceneIDs[sceneIdxWithGallery]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithGallery], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithGallery], performerIDs[performerIdx1WithDupName]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -441,9 +479,9 @@ func Test_galleryQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
Files: []file.File{
|
||||
makeGalleryFile(galleryIdxWithImage),
|
||||
},
|
||||
SceneIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
SceneIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -472,6 +510,11 @@ func Test_galleryQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
}
|
||||
|
||||
clearGalleryFileIDs(got)
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want, *got)
|
||||
|
||||
s, err := qb.Find(ctx, tt.id)
|
||||
@@ -480,6 +523,11 @@ func Test_galleryQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
}
|
||||
|
||||
clearGalleryFileIDs(s)
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, tt.want, s); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want, *s)
|
||||
})
|
||||
}
|
||||
@@ -503,10 +551,10 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
SceneIDs: append(indexesToIDs(sceneIDs, sceneGalleries.reverseLookup(galleryIdx1WithImage)),
|
||||
SceneIDs: models.NewRelatedIDs(append(indexesToIDs(sceneIDs, sceneGalleries.reverseLookup(galleryIdx1WithImage)),
|
||||
sceneIDs[sceneIdx1WithStudio],
|
||||
sceneIDs[sceneIdx1WithPerformer],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -520,10 +568,10 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
TagIDs: append(indexesToIDs(tagIDs, galleryTags[galleryIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(append(indexesToIDs(tagIDs, galleryTags[galleryIdxWithTwoTags]),
|
||||
tagIDs[tagIdx1WithDupName],
|
||||
tagIDs[tagIdx1WithImage],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -537,10 +585,10 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
PerformerIDs: append(indexesToIDs(performerIDs, galleryPerformers[galleryIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(append(indexesToIDs(performerIDs, galleryPerformers[galleryIdxWithTwoPerformers]),
|
||||
performerIDs[performerIdx1WithDupName],
|
||||
performerIDs[performerIdx1WithImage],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -554,9 +602,9 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
SceneIDs: append(indexesToIDs(sceneIDs, sceneGalleries.reverseLookup(galleryIdxWithScene)),
|
||||
SceneIDs: models.NewRelatedIDs(append(indexesToIDs(sceneIDs, sceneGalleries.reverseLookup(galleryIdxWithScene)),
|
||||
sceneIDs[sceneIdx1WithPerformer],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -570,9 +618,9 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
TagIDs: append(indexesToIDs(tagIDs, galleryTags[galleryIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(append(indexesToIDs(tagIDs, galleryTags[galleryIdxWithTwoTags]),
|
||||
tagIDs[tagIdx1WithScene],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -586,9 +634,9 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
PerformerIDs: append(indexesToIDs(performerIDs, galleryPerformers[galleryIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(append(indexesToIDs(performerIDs, galleryPerformers[galleryIdxWithTwoPerformers]),
|
||||
performerIDs[performerIdx1WithScene],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -638,7 +686,7 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
SceneIDs: []int{},
|
||||
SceneIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -652,7 +700,7 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
TagIDs: []int{tagIDs[tagIdx2WithGallery]},
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx2WithGallery]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -666,7 +714,7 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
PerformerIDs: []int{performerIDs[performerIdx2WithGallery]},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx2WithGallery]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -680,7 +728,7 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
SceneIDs: []int{sceneIDs[sceneIdxWithGallery]},
|
||||
SceneIDs: models.NewRelatedIDs([]int{sceneIDs[sceneIdxWithGallery]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -694,7 +742,7 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
TagIDs: indexesToIDs(tagIDs, galleryTags[galleryIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(indexesToIDs(tagIDs, galleryTags[galleryIdxWithTwoTags])),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -708,7 +756,7 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Gallery{
|
||||
PerformerIDs: indexesToIDs(performerIDs, galleryPerformers[galleryIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(indexesToIDs(performerIDs, galleryPerformers[galleryIdxWithTwoPerformers])),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -735,6 +783,16 @@ func Test_galleryQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
t.Errorf("galleryQueryBuilder.Find() error = %v", err)
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
if err := loadGalleryRelationships(ctx, tt.want, s); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// only compare fields that were in the partial
|
||||
if tt.partial.PerformerIDs != nil {
|
||||
assert.Equal(tt.want.PerformerIDs, got.PerformerIDs)
|
||||
@@ -851,12 +909,33 @@ func Test_galleryQueryBuilder_Find(t *testing.T) {
|
||||
|
||||
if got != nil {
|
||||
clearGalleryFileIDs(got)
|
||||
|
||||
// load relationships
|
||||
if err := loadGalleryRelationships(ctx, *tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
assert.Equal(tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func postFindGalleries(ctx context.Context, want []*models.Gallery, got []*models.Gallery) error {
|
||||
for i, s := range got {
|
||||
clearGalleryFileIDs(s)
|
||||
|
||||
// load relationships
|
||||
if i < len(want) {
|
||||
if err := loadGalleryRelationships(ctx, *want[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_galleryQueryBuilder_FindMany(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -893,8 +972,9 @@ func Test_galleryQueryBuilder_FindMany(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearGalleryFileIDs(f)
|
||||
if err := postFindGalleries(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -950,8 +1030,9 @@ func Test_galleryQueryBuilder_FindByChecksum(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearGalleryFileIDs(f)
|
||||
if err := postFindGalleries(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1012,8 +1093,9 @@ func Test_galleryQueryBuilder_FindByChecksums(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearGalleryFileIDs(f)
|
||||
if err := postFindGalleries(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1069,8 +1151,9 @@ func Test_galleryQueryBuilder_FindByPath(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearGalleryFileIDs(f)
|
||||
if err := postFindGalleries(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1110,8 +1193,9 @@ func Test_galleryQueryBuilder_FindBySceneID(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearGalleryFileIDs(f)
|
||||
if err := postFindGalleries(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1154,8 +1238,9 @@ func Test_galleryQueryBuilder_FindByImageID(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearGalleryFileIDs(f)
|
||||
if err := postFindGalleries(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadGalleryRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -2143,7 +2228,11 @@ func verifyGalleriesTagCount(t *testing.T, tagCountCriterion models.IntCriterion
|
||||
assert.Greater(t, len(galleries), 0)
|
||||
|
||||
for _, gallery := range galleries {
|
||||
verifyInt(t, len(gallery.TagIDs), tagCountCriterion)
|
||||
if err := gallery.LoadTagIDs(ctx, sqb); err != nil {
|
||||
t.Errorf("gallery.LoadTagIDs() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
verifyInt(t, len(gallery.TagIDs.List()), tagCountCriterion)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -2180,7 +2269,12 @@ func verifyGalleriesPerformerCount(t *testing.T, performerCountCriterion models.
|
||||
assert.Greater(t, len(galleries), 0)
|
||||
|
||||
for _, gallery := range galleries {
|
||||
verifyInt(t, len(gallery.PerformerIDs), performerCountCriterion)
|
||||
if err := gallery.LoadPerformerIDs(ctx, sqb); err != nil {
|
||||
t.Errorf("gallery.LoadPerformerIDs() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
verifyInt(t, len(gallery.PerformerIDs.List()), performerCountCriterion)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -116,18 +116,19 @@ func (qb *ImageStore) Create(ctx context.Context, newObject *models.ImageCreateI
|
||||
}
|
||||
}
|
||||
|
||||
if len(newObject.GalleryIDs) > 0 {
|
||||
if err := imageGalleriesTableMgr.insertJoins(ctx, id, newObject.GalleryIDs); err != nil {
|
||||
if newObject.PerformerIDs.Loaded() {
|
||||
if err := imagesPerformersTableMgr.insertJoins(ctx, id, newObject.PerformerIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(newObject.PerformerIDs) > 0 {
|
||||
if err := imagesPerformersTableMgr.insertJoins(ctx, id, newObject.PerformerIDs); err != nil {
|
||||
if newObject.TagIDs.Loaded() {
|
||||
if err := imagesTagsTableMgr.insertJoins(ctx, id, newObject.TagIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(newObject.TagIDs) > 0 {
|
||||
if err := imagesTagsTableMgr.insertJoins(ctx, id, newObject.TagIDs); err != nil {
|
||||
|
||||
if newObject.GalleryIDs.Loaded() {
|
||||
if err := imageGalleriesTableMgr.insertJoins(ctx, id, newObject.GalleryIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -184,14 +185,22 @@ func (qb *ImageStore) Update(ctx context.Context, updatedObject *models.Image) e
|
||||
return err
|
||||
}
|
||||
|
||||
if err := imageGalleriesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.GalleryIDs); err != nil {
|
||||
return err
|
||||
if updatedObject.PerformerIDs.Loaded() {
|
||||
if err := imagesPerformersTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.PerformerIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := imagesPerformersTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.PerformerIDs); err != nil {
|
||||
return err
|
||||
|
||||
if updatedObject.TagIDs.Loaded() {
|
||||
if err := imagesTagsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.TagIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := imagesTagsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.TagIDs); err != nil {
|
||||
return err
|
||||
|
||||
if updatedObject.GalleryIDs.Loaded() {
|
||||
if err := imageGalleriesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.GalleryIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fileIDs := make([]file.ID, len(updatedObject.Files))
|
||||
@@ -265,16 +274,18 @@ func (qb *ImageStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*mo
|
||||
|
||||
i := f.resolve()
|
||||
|
||||
if err := qb.resolveRelationships(ctx, i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, i)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, i := range ret {
|
||||
if err := qb.resolveRelationships(ctx, i); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -287,24 +298,6 @@ func (qb *ImageStore) resolveRelationships(ctx context.Context, i *models.Image)
|
||||
return fmt.Errorf("resolving image files: %w", err)
|
||||
}
|
||||
|
||||
// performers
|
||||
i.PerformerIDs, err = qb.performersRepository().getIDs(ctx, i.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving image performers: %w", err)
|
||||
}
|
||||
|
||||
// tags
|
||||
i.TagIDs, err = qb.tagsRepository().getIDs(ctx, i.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving image tags: %w", err)
|
||||
}
|
||||
|
||||
// galleries
|
||||
i.GalleryIDs, err = qb.galleriesRepository().getIDs(ctx, i.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving image galleries: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1004,9 +997,14 @@ func (qb *ImageStore) filesRepository() *filesRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// func (qb *imageQueryBuilder) GetGalleryIDs(ctx context.Context, imageID int) ([]int, error) {
|
||||
// return qb.galleriesRepository().getIDs(ctx, imageID)
|
||||
// }
|
||||
func (qb *ImageStore) AddFileID(ctx context.Context, id int, fileID file.ID) error {
|
||||
const firstPrimary = false
|
||||
return imagesFilesTableMgr.insertJoins(ctx, id, firstPrimary, []file.ID{fileID})
|
||||
}
|
||||
|
||||
func (qb *ImageStore) GetGalleryIDs(ctx context.Context, imageID int) ([]int, error) {
|
||||
return qb.galleriesRepository().getIDs(ctx, imageID)
|
||||
}
|
||||
|
||||
// func (qb *imageQueryBuilder) UpdateGalleries(ctx context.Context, imageID int, galleryIDs []int) error {
|
||||
// // Delete the existing joins and then create new ones
|
||||
|
||||
@@ -15,6 +15,26 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func loadImageRelationships(ctx context.Context, expected models.Image, actual *models.Image) error {
|
||||
if expected.GalleryIDs.Loaded() {
|
||||
if err := actual.LoadGalleryIDs(ctx, db.Image); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.TagIDs.Loaded() {
|
||||
if err := actual.LoadTagIDs(ctx, db.Image); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.PerformerIDs.Loaded() {
|
||||
if err := actual.LoadPerformerIDs(ctx, db.Image); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_imageQueryBuilder_Create(t *testing.T) {
|
||||
var (
|
||||
title = "title"
|
||||
@@ -41,9 +61,9 @@ func Test_imageQueryBuilder_Create(t *testing.T) {
|
||||
StudioID: &studioIDs[studioIdxWithImage],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithImage]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithImage]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]}),
|
||||
Files: []*file.ImageFile{},
|
||||
},
|
||||
false,
|
||||
@@ -61,9 +81,9 @@ func Test_imageQueryBuilder_Create(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithImage]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithImage]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -77,21 +97,21 @@ func Test_imageQueryBuilder_Create(t *testing.T) {
|
||||
{
|
||||
"invalid gallery id",
|
||||
models.Image{
|
||||
GalleryIDs: []int{invalidID},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid tag id",
|
||||
models.Image{
|
||||
TagIDs: []int{invalidID},
|
||||
TagIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid performer id",
|
||||
models.Image{
|
||||
PerformerIDs: []int{invalidID},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -126,6 +146,12 @@ func Test_imageQueryBuilder_Create(t *testing.T) {
|
||||
copy := tt.newObject
|
||||
copy.ID = s.ID
|
||||
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, copy, &s); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, s)
|
||||
|
||||
// ensure can find the image
|
||||
@@ -134,6 +160,12 @@ func Test_imageQueryBuilder_Create(t *testing.T) {
|
||||
t.Errorf("imageQueryBuilder.Find() error = %v", err)
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, copy, found); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, *found)
|
||||
|
||||
return
|
||||
@@ -181,9 +213,9 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithImage]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithImage]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -194,9 +226,9 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.ImageFile{
|
||||
makeImageFileWithID(imageIdxWithGallery),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -210,9 +242,9 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.ImageFile{
|
||||
makeImageFileWithID(imageIdxWithGallery),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -226,9 +258,9 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.ImageFile{
|
||||
makeImageFileWithID(imageIdxWithTag),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -242,9 +274,9 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.ImageFile{
|
||||
makeImageFileWithID(imageIdxWithPerformer),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Organized: true,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
@@ -273,7 +305,7 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
makeImageFileWithID(imageIdxWithGallery),
|
||||
},
|
||||
Organized: true,
|
||||
GalleryIDs: []int{invalidID},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
},
|
||||
@@ -287,7 +319,7 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
makeImageFileWithID(imageIdxWithGallery),
|
||||
},
|
||||
Organized: true,
|
||||
TagIDs: []int{invalidID},
|
||||
TagIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
},
|
||||
@@ -301,7 +333,7 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
makeImageFileWithID(imageIdxWithGallery),
|
||||
},
|
||||
Organized: true,
|
||||
PerformerIDs: []int{invalidID},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
},
|
||||
@@ -329,6 +361,12 @@ func Test_imageQueryBuilder_Update(t *testing.T) {
|
||||
t.Errorf("imageQueryBuilder.Find() error = %v", err)
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, copy, s); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, *s)
|
||||
|
||||
return
|
||||
@@ -400,9 +438,9 @@ func Test_imageQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithImage]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithImage]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithImage], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithImage], performerIDs[performerIdx1WithDupName]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -416,9 +454,9 @@ func Test_imageQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
Files: []*file.ImageFile{
|
||||
makeImageFile(imageIdx1WithGallery),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -447,6 +485,12 @@ func Test_imageQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
}
|
||||
|
||||
clearImageFileIDs(got)
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, *got)
|
||||
|
||||
s, err := qb.Find(ctx, tt.id)
|
||||
@@ -455,6 +499,11 @@ func Test_imageQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
}
|
||||
|
||||
clearImageFileIDs(s)
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, tt.want, s); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want, *s)
|
||||
})
|
||||
}
|
||||
@@ -478,10 +527,10 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
GalleryIDs: append(indexesToIDs(galleryIDs, imageGalleries[imageIdxWithGallery]),
|
||||
GalleryIDs: models.NewRelatedIDs(append(indexesToIDs(galleryIDs, imageGalleries[imageIdxWithGallery]),
|
||||
galleryIDs[galleryIdx1WithImage],
|
||||
galleryIDs[galleryIdx1WithPerformer],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -495,10 +544,10 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
TagIDs: append(indexesToIDs(tagIDs, imageTags[imageIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(append(indexesToIDs(tagIDs, imageTags[imageIdxWithTwoTags]),
|
||||
tagIDs[tagIdx1WithDupName],
|
||||
tagIDs[tagIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -512,10 +561,10 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
PerformerIDs: append(indexesToIDs(performerIDs, imagePerformers[imageIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(append(indexesToIDs(performerIDs, imagePerformers[imageIdxWithTwoPerformers]),
|
||||
performerIDs[performerIdx1WithDupName],
|
||||
performerIDs[performerIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -529,9 +578,9 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
GalleryIDs: append(indexesToIDs(galleryIDs, imageGalleries[imageIdxWithGallery]),
|
||||
GalleryIDs: models.NewRelatedIDs(append(indexesToIDs(galleryIDs, imageGalleries[imageIdxWithGallery]),
|
||||
galleryIDs[galleryIdx1WithPerformer],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -545,9 +594,9 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
TagIDs: append(indexesToIDs(tagIDs, imageTags[imageIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(append(indexesToIDs(tagIDs, imageTags[imageIdxWithTwoTags]),
|
||||
tagIDs[tagIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -561,9 +610,9 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
PerformerIDs: append(indexesToIDs(performerIDs, imagePerformers[imageIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(append(indexesToIDs(performerIDs, imagePerformers[imageIdxWithTwoPerformers]),
|
||||
performerIDs[performerIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -613,7 +662,7 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
GalleryIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -627,7 +676,7 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
TagIDs: []int{tagIDs[tagIdx2WithImage]},
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx2WithImage]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -641,7 +690,7 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
PerformerIDs: []int{performerIDs[performerIdx2WithImage]},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx2WithImage]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -655,7 +704,7 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithImage]},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithImage]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -669,7 +718,7 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
TagIDs: indexesToIDs(tagIDs, imageTags[imageIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(indexesToIDs(tagIDs, imageTags[imageIdxWithTwoTags])),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -683,7 +732,7 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Image{
|
||||
PerformerIDs: indexesToIDs(performerIDs, imagePerformers[imageIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(indexesToIDs(performerIDs, imagePerformers[imageIdxWithTwoPerformers])),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -710,6 +759,16 @@ func Test_imageQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
t.Errorf("imageQueryBuilder.Find() error = %v", err)
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
if err := loadImageRelationships(ctx, tt.want, s); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// only compare fields that were in the partial
|
||||
if tt.partial.PerformerIDs != nil {
|
||||
assert.Equal(tt.want.PerformerIDs, got.PerformerIDs)
|
||||
@@ -944,12 +1003,33 @@ func Test_imageQueryBuilder_Find(t *testing.T) {
|
||||
|
||||
if got != nil {
|
||||
clearImageFileIDs(got)
|
||||
|
||||
// load relationships
|
||||
if err := loadImageRelationships(ctx, *tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
assert.Equal(tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func postFindImages(ctx context.Context, want []*models.Image, got []*models.Image) error {
|
||||
for i, s := range got {
|
||||
clearImageFileIDs(s)
|
||||
|
||||
// load relationships
|
||||
if i < len(want) {
|
||||
if err := loadImageRelationships(ctx, *want[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_imageQueryBuilder_FindMany(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -985,8 +1065,9 @@ func Test_imageQueryBuilder_FindMany(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearImageFileIDs(f)
|
||||
if err := postFindImages(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
@@ -1044,8 +1125,9 @@ func Test_imageQueryBuilder_FindByChecksum(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearImageFileIDs(f)
|
||||
if err := postFindImages(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1121,8 +1203,9 @@ func Test_imageQueryBuilder_FindByFingerprints(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearImageFileIDs(f)
|
||||
if err := postFindImages(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1162,8 +1245,9 @@ func Test_imageQueryBuilder_FindByGalleryID(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range got {
|
||||
clearImageFileIDs(f)
|
||||
if err := postFindImages(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadImageRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
@@ -6,7 +6,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/doug-martin/goqu/v9"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
)
|
||||
|
||||
const movieTable = "movies"
|
||||
@@ -66,21 +69,45 @@ func (qb *movieQueryBuilder) Find(ctx context.Context, id int) (*models.Movie, e
|
||||
}
|
||||
|
||||
func (qb *movieQueryBuilder) FindMany(ctx context.Context, ids []int) ([]*models.Movie, error) {
|
||||
var movies []*models.Movie
|
||||
for _, id := range ids {
|
||||
movie, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if movie == nil {
|
||||
return nil, fmt.Errorf("movie with id %d not found", id)
|
||||
}
|
||||
|
||||
movies = append(movies, movie)
|
||||
tableMgr := movieTableMgr
|
||||
q := goqu.Select("*").From(tableMgr.table).Where(tableMgr.byIDInts(ids...))
|
||||
unsorted, err := qb.getMany(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return movies, nil
|
||||
ret := make([]*models.Movie, len(ids))
|
||||
|
||||
for _, s := range unsorted {
|
||||
i := intslice.IntIndex(ids, s.ID)
|
||||
ret[i] = s
|
||||
}
|
||||
|
||||
for i := range ret {
|
||||
if ret[i] == nil {
|
||||
return nil, fmt.Errorf("movie with id %d not found", ids[i])
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *movieQueryBuilder) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*models.Movie, error) {
|
||||
const single = false
|
||||
var ret []*models.Movie
|
||||
if err := queryFunc(ctx, q, single, func(r *sqlx.Rows) error {
|
||||
var f models.Movie
|
||||
if err := r.StructScan(&f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, &f)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *movieQueryBuilder) FindByName(ctx context.Context, name string, nocase bool) (*models.Movie, error) {
|
||||
@@ -156,14 +183,9 @@ func (qb *movieQueryBuilder) Query(ctx context.Context, movieFilter *models.Movi
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var movies []*models.Movie
|
||||
for _, id := range idsResult {
|
||||
movie, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
movies = append(movies, movie)
|
||||
movies, err := qb.FindMany(ctx, idsResult)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return movies, countResult, nil
|
||||
|
||||
@@ -7,7 +7,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
"github.com/stashapp/stash/pkg/utils"
|
||||
)
|
||||
|
||||
@@ -92,21 +95,45 @@ func (qb *performerQueryBuilder) Find(ctx context.Context, id int) (*models.Perf
|
||||
}
|
||||
|
||||
func (qb *performerQueryBuilder) FindMany(ctx context.Context, ids []int) ([]*models.Performer, error) {
|
||||
var performers []*models.Performer
|
||||
for _, id := range ids {
|
||||
performer, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if performer == nil {
|
||||
return nil, fmt.Errorf("performer with id %d not found", id)
|
||||
}
|
||||
|
||||
performers = append(performers, performer)
|
||||
tableMgr := performerTableMgr
|
||||
q := goqu.Select("*").From(tableMgr.table).Where(tableMgr.byIDInts(ids...))
|
||||
unsorted, err := qb.getMany(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return performers, nil
|
||||
ret := make([]*models.Performer, len(ids))
|
||||
|
||||
for _, s := range unsorted {
|
||||
i := intslice.IntIndex(ids, s.ID)
|
||||
ret[i] = s
|
||||
}
|
||||
|
||||
for i := range ret {
|
||||
if ret[i] == nil {
|
||||
return nil, fmt.Errorf("performer with id %d not found", ids[i])
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *performerQueryBuilder) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*models.Performer, error) {
|
||||
const single = false
|
||||
var ret []*models.Performer
|
||||
if err := queryFunc(ctx, q, single, func(r *sqlx.Rows) error {
|
||||
var f models.Performer
|
||||
if err := r.StructScan(&f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, &f)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *performerQueryBuilder) FindBySceneID(ctx context.Context, sceneID int) ([]*models.Performer, error) {
|
||||
@@ -324,13 +351,9 @@ func (qb *performerQueryBuilder) Query(ctx context.Context, performerFilter *mod
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var performers []*models.Performer
|
||||
for _, id := range idsResult {
|
||||
performer, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
performers = append(performers, performer)
|
||||
performers, err := qb.FindMany(ctx, idsResult)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return performers, countResult, nil
|
||||
@@ -600,11 +623,11 @@ func (qb *performerQueryBuilder) stashIDRepository() *stashIDRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *performerQueryBuilder) GetStashIDs(ctx context.Context, performerID int) ([]*models.StashID, error) {
|
||||
func (qb *performerQueryBuilder) GetStashIDs(ctx context.Context, performerID int) ([]models.StashID, error) {
|
||||
return qb.stashIDRepository().get(ctx, performerID)
|
||||
}
|
||||
|
||||
func (qb *performerQueryBuilder) UpdateStashIDs(ctx context.Context, performerID int, stashIDs []*models.StashID) error {
|
||||
func (qb *performerQueryBuilder) UpdateStashIDs(ctx context.Context, performerID int, stashIDs []models.StashID) error {
|
||||
return qb.stashIDRepository().replace(ctx, performerID, stashIDs)
|
||||
}
|
||||
|
||||
|
||||
@@ -441,24 +441,24 @@ type stashIDRepository struct {
|
||||
repository
|
||||
}
|
||||
|
||||
type stashIDs []*models.StashID
|
||||
type stashIDs []models.StashID
|
||||
|
||||
func (s *stashIDs) Append(o interface{}) {
|
||||
*s = append(*s, o.(*models.StashID))
|
||||
*s = append(*s, *o.(*models.StashID))
|
||||
}
|
||||
|
||||
func (s *stashIDs) New() interface{} {
|
||||
return &models.StashID{}
|
||||
}
|
||||
|
||||
func (r *stashIDRepository) get(ctx context.Context, id int) ([]*models.StashID, error) {
|
||||
func (r *stashIDRepository) get(ctx context.Context, id int) ([]models.StashID, error) {
|
||||
query := fmt.Sprintf("SELECT stash_id, endpoint from %s WHERE %s = ?", r.tableName, r.idColumn)
|
||||
var ret stashIDs
|
||||
err := r.query(ctx, query, []interface{}{id}, &ret)
|
||||
return []*models.StashID(ret), err
|
||||
return []models.StashID(ret), err
|
||||
}
|
||||
|
||||
func (r *stashIDRepository) replace(ctx context.Context, id int, newIDs []*models.StashID) error {
|
||||
func (r *stashIDRepository) replace(ctx context.Context, id int, newIDs []models.StashID) error {
|
||||
if err := r.destroy(ctx, []int{id}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -157,20 +157,33 @@ func (qb *SceneStore) Create(ctx context.Context, newObject *models.Scene, fileI
|
||||
}
|
||||
}
|
||||
|
||||
if err := scenesPerformersTableMgr.insertJoins(ctx, id, newObject.PerformerIDs); err != nil {
|
||||
return err
|
||||
if newObject.PerformerIDs.Loaded() {
|
||||
if err := scenesPerformersTableMgr.insertJoins(ctx, id, newObject.PerformerIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesTagsTableMgr.insertJoins(ctx, id, newObject.TagIDs); err != nil {
|
||||
return err
|
||||
if newObject.TagIDs.Loaded() {
|
||||
if err := scenesTagsTableMgr.insertJoins(ctx, id, newObject.TagIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesGalleriesTableMgr.insertJoins(ctx, id, newObject.GalleryIDs); err != nil {
|
||||
return err
|
||||
|
||||
if newObject.GalleryIDs.Loaded() {
|
||||
if err := scenesGalleriesTableMgr.insertJoins(ctx, id, newObject.GalleryIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesStashIDsTableMgr.insertJoins(ctx, id, newObject.StashIDs); err != nil {
|
||||
return err
|
||||
|
||||
if newObject.StashIDs.Loaded() {
|
||||
if err := scenesStashIDsTableMgr.insertJoins(ctx, id, newObject.StashIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesMoviesTableMgr.insertJoins(ctx, id, newObject.Movies); err != nil {
|
||||
return err
|
||||
|
||||
if newObject.Movies.Loaded() {
|
||||
if err := scenesMoviesTableMgr.insertJoins(ctx, id, newObject.Movies.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
updated, err := qb.find(ctx, id)
|
||||
@@ -235,20 +248,34 @@ func (qb *SceneStore) Update(ctx context.Context, updatedObject *models.Scene) e
|
||||
return err
|
||||
}
|
||||
|
||||
if err := scenesPerformersTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.PerformerIDs); err != nil {
|
||||
return err
|
||||
if updatedObject.PerformerIDs.Loaded() {
|
||||
if err := scenesPerformersTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.PerformerIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesTagsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.TagIDs); err != nil {
|
||||
return err
|
||||
|
||||
if updatedObject.TagIDs.Loaded() {
|
||||
if err := scenesTagsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.TagIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesGalleriesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.GalleryIDs); err != nil {
|
||||
return err
|
||||
|
||||
if updatedObject.GalleryIDs.Loaded() {
|
||||
if err := scenesGalleriesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.GalleryIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesStashIDsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.StashIDs); err != nil {
|
||||
return err
|
||||
|
||||
if updatedObject.StashIDs.Loaded() {
|
||||
if err := scenesStashIDsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.StashIDs.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := scenesMoviesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.Movies); err != nil {
|
||||
return err
|
||||
|
||||
if updatedObject.Movies.Loaded() {
|
||||
if err := scenesMoviesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.Movies.List()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fileIDs := make([]file.ID, len(updatedObject.Files))
|
||||
@@ -333,16 +360,18 @@ func (qb *SceneStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*mo
|
||||
|
||||
s := f.resolve()
|
||||
|
||||
if err := qb.resolveRelationships(ctx, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, s)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, s := range ret {
|
||||
if err := qb.resolveRelationships(ctx, s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -355,36 +384,6 @@ func (qb *SceneStore) resolveRelationships(ctx context.Context, s *models.Scene)
|
||||
return fmt.Errorf("resolving scene files: %w", err)
|
||||
}
|
||||
|
||||
// movies
|
||||
s.Movies, err = qb.getMovies(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving scene movies: %w", err)
|
||||
}
|
||||
|
||||
// performers
|
||||
s.PerformerIDs, err = qb.performersRepository().getIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving scene performers: %w", err)
|
||||
}
|
||||
|
||||
// tags
|
||||
s.TagIDs, err = qb.tagsRepository().getIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving scene tags: %w", err)
|
||||
}
|
||||
|
||||
// galleries
|
||||
s.GalleryIDs, err = qb.galleriesRepository().getIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving scene galleries: %w", err)
|
||||
}
|
||||
|
||||
// stash ids
|
||||
s.StashIDs, err = qb.getStashIDs(ctx, s.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving scene stash ids: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -412,37 +411,6 @@ func (qb *SceneStore) getFiles(ctx context.Context, id int) ([]*file.VideoFile,
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *SceneStore) getMovies(ctx context.Context, id int) (ret []models.MoviesScenes, err error) {
|
||||
ret = []models.MoviesScenes{}
|
||||
if err := qb.moviesRepository().getAll(ctx, id, func(rows *sqlx.Rows) error {
|
||||
var ms moviesScenesRow
|
||||
if err := rows.StructScan(&ms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, ms.resolve(id))
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *SceneStore) getStashIDs(ctx context.Context, id int) ([]models.StashID, error) {
|
||||
stashIDs, err := qb.stashIDRepository().get(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := make([]models.StashID, len(stashIDs))
|
||||
for i, sid := range stashIDs {
|
||||
ret[i] = *sid
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *SceneStore) find(ctx context.Context, id int) (*models.Scene, error) {
|
||||
q := qb.selectDataset().Where(qb.tableMgr.byID(id))
|
||||
|
||||
@@ -1399,6 +1367,24 @@ func (qb *SceneStore) moviesRepository() *repository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *SceneStore) GetMovies(ctx context.Context, id int) (ret []models.MoviesScenes, err error) {
|
||||
ret = []models.MoviesScenes{}
|
||||
|
||||
if err := qb.moviesRepository().getAll(ctx, id, func(rows *sqlx.Rows) error {
|
||||
var ms moviesScenesRow
|
||||
if err := rows.StructScan(&ms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, ms.resolve(id))
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *SceneStore) filesRepository() *filesRepository {
|
||||
return &filesRepository{
|
||||
repository: repository{
|
||||
@@ -1409,6 +1395,11 @@ func (qb *SceneStore) filesRepository() *filesRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *SceneStore) AddFileID(ctx context.Context, id int, fileID file.ID) error {
|
||||
const firstPrimary = false
|
||||
return scenesFilesTableMgr.insertJoins(ctx, id, firstPrimary, []file.ID{fileID})
|
||||
}
|
||||
|
||||
func (qb *SceneStore) performersRepository() *joinRepository {
|
||||
return &joinRepository{
|
||||
repository: repository{
|
||||
@@ -1420,6 +1411,10 @@ func (qb *SceneStore) performersRepository() *joinRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *SceneStore) GetPerformerIDs(ctx context.Context, id int) ([]int, error) {
|
||||
return qb.performersRepository().getIDs(ctx, id)
|
||||
}
|
||||
|
||||
func (qb *SceneStore) tagsRepository() *joinRepository {
|
||||
return &joinRepository{
|
||||
repository: repository{
|
||||
@@ -1431,6 +1426,10 @@ func (qb *SceneStore) tagsRepository() *joinRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *SceneStore) GetTagIDs(ctx context.Context, id int) ([]int, error) {
|
||||
return qb.tagsRepository().getIDs(ctx, id)
|
||||
}
|
||||
|
||||
func (qb *SceneStore) galleriesRepository() *joinRepository {
|
||||
return &joinRepository{
|
||||
repository: repository{
|
||||
@@ -1442,6 +1441,14 @@ func (qb *SceneStore) galleriesRepository() *joinRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *SceneStore) GetGalleryIDs(ctx context.Context, id int) ([]int, error) {
|
||||
return qb.galleriesRepository().getIDs(ctx, id)
|
||||
}
|
||||
|
||||
func (qb *SceneStore) AddGalleryIDs(ctx context.Context, sceneID int, galleryIDs []int) error {
|
||||
return scenesGalleriesTableMgr.addJoins(ctx, sceneID, galleryIDs)
|
||||
}
|
||||
|
||||
func (qb *SceneStore) stashIDRepository() *stashIDRepository {
|
||||
return &stashIDRepository{
|
||||
repository{
|
||||
@@ -1452,6 +1459,10 @@ func (qb *SceneStore) stashIDRepository() *stashIDRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *SceneStore) GetStashIDs(ctx context.Context, sceneID int) ([]models.StashID, error) {
|
||||
return qb.stashIDRepository().get(ctx, sceneID)
|
||||
}
|
||||
|
||||
func (qb *SceneStore) FindDuplicates(ctx context.Context, distance int) ([][]*models.Scene, error) {
|
||||
var dupeIds [][]int
|
||||
if distance == 0 {
|
||||
|
||||
@@ -157,7 +157,13 @@ func TestMarkerQuerySceneTags(t *testing.T) {
|
||||
t.Errorf("error getting marker tag ids: %v", err)
|
||||
return
|
||||
}
|
||||
tagIDs := s.TagIDs
|
||||
|
||||
if err := s.LoadTagIDs(ctx, db.Scene); err != nil {
|
||||
t.Errorf("error getting marker tag ids: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tagIDs := s.TagIDs.List()
|
||||
if markerFilter.SceneTags.Modifier == models.CriterionModifierIsNull && len(tagIDs) > 0 {
|
||||
t.Errorf("expected marker %d to have no scene tags - found %d", m.ID, len(tagIDs))
|
||||
}
|
||||
|
||||
@@ -21,6 +21,36 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func loadSceneRelationships(ctx context.Context, expected models.Scene, actual *models.Scene) error {
|
||||
if expected.GalleryIDs.Loaded() {
|
||||
if err := actual.LoadGalleryIDs(ctx, db.Scene); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.TagIDs.Loaded() {
|
||||
if err := actual.LoadTagIDs(ctx, db.Scene); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.PerformerIDs.Loaded() {
|
||||
if err := actual.LoadPerformerIDs(ctx, db.Scene); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.Movies.Loaded() {
|
||||
if err := actual.LoadMovies(ctx, db.Scene); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if expected.StashIDs.Loaded() {
|
||||
if err := actual.LoadStashIDs(ctx, db.Scene); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
var (
|
||||
title = "title"
|
||||
@@ -60,10 +90,10 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithScene]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
Movies: []models.MoviesScenes{
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: movieIDs[movieIdxWithScene],
|
||||
SceneIndex: &sceneIndex,
|
||||
@@ -72,8 +102,8 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
MovieID: movieIDs[movieIdxWithStudio],
|
||||
SceneIndex: &sceneIndex2,
|
||||
},
|
||||
},
|
||||
StashIDs: []models.StashID{
|
||||
}),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{
|
||||
{
|
||||
StashID: stashID1,
|
||||
Endpoint: endpoint1,
|
||||
@@ -82,7 +112,7 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
StashID: stashID2,
|
||||
Endpoint: endpoint2,
|
||||
},
|
||||
},
|
||||
}),
|
||||
Files: []*file.VideoFile{},
|
||||
},
|
||||
false,
|
||||
@@ -103,10 +133,10 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithScene]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
Movies: []models.MoviesScenes{
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: movieIDs[movieIdxWithScene],
|
||||
SceneIndex: &sceneIndex,
|
||||
@@ -115,8 +145,8 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
MovieID: movieIDs[movieIdxWithStudio],
|
||||
SceneIndex: &sceneIndex2,
|
||||
},
|
||||
},
|
||||
StashIDs: []models.StashID{
|
||||
}),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{
|
||||
{
|
||||
StashID: stashID1,
|
||||
Endpoint: endpoint1,
|
||||
@@ -125,7 +155,7 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
StashID: stashID2,
|
||||
Endpoint: endpoint2,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -139,33 +169,33 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
{
|
||||
"invalid gallery id",
|
||||
models.Scene{
|
||||
GalleryIDs: []int{invalidID},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid tag id",
|
||||
models.Scene{
|
||||
TagIDs: []int{invalidID},
|
||||
TagIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid performer id",
|
||||
models.Scene{
|
||||
PerformerIDs: []int{invalidID},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid movie id",
|
||||
models.Scene{
|
||||
Movies: []models.MoviesScenes{
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: invalidID,
|
||||
SceneIndex: &sceneIndex,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -197,6 +227,12 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
copy := tt.newObject
|
||||
copy.ID = s.ID
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, copy, &s); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, s)
|
||||
|
||||
// ensure can find the scene
|
||||
@@ -208,6 +244,12 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
||||
if !assert.NotNil(found) {
|
||||
return
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, copy, found); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
assert.Equal(copy, *found)
|
||||
|
||||
return
|
||||
@@ -268,10 +310,10 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithScene]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
Movies: []models.MoviesScenes{
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: movieIDs[movieIdxWithScene],
|
||||
SceneIndex: &sceneIndex,
|
||||
@@ -280,8 +322,8 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
MovieID: movieIDs[movieIdxWithStudio],
|
||||
SceneIndex: &sceneIndex2,
|
||||
},
|
||||
},
|
||||
StashIDs: []models.StashID{
|
||||
}),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{
|
||||
{
|
||||
StashID: stashID1,
|
||||
Endpoint: endpoint1,
|
||||
@@ -290,7 +332,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
StashID: stashID2,
|
||||
Endpoint: endpoint2,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -301,11 +343,11 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithSpacedName),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
Movies: []models.MoviesScenes{},
|
||||
StashIDs: []models.StashID{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -316,11 +358,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithGallery),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
Movies: []models.MoviesScenes{},
|
||||
StashIDs: []models.StashID{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -331,11 +369,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithTag),
|
||||
},
|
||||
TagIDs: []int{},
|
||||
GalleryIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
Movies: []models.MoviesScenes{},
|
||||
StashIDs: []models.StashID{},
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -346,11 +380,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithPerformer),
|
||||
},
|
||||
PerformerIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
GalleryIDs: []int{},
|
||||
Movies: []models.MoviesScenes{},
|
||||
StashIDs: []models.StashID{},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -361,11 +391,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithMovie),
|
||||
},
|
||||
Movies: []models.MoviesScenes{},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
StashIDs: []models.StashID{},
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -376,12 +402,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithGallery),
|
||||
},
|
||||
StudioID: &invalidID,
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
Movies: []models.MoviesScenes{},
|
||||
StashIDs: []models.StashID{},
|
||||
StudioID: &invalidID,
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -392,7 +413,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithGallery),
|
||||
},
|
||||
GalleryIDs: []int{invalidID},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -403,7 +424,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithGallery),
|
||||
},
|
||||
TagIDs: []int{invalidID},
|
||||
TagIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -414,7 +435,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithGallery),
|
||||
},
|
||||
PerformerIDs: []int{invalidID},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{invalidID}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -425,12 +446,12 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFileWithID(sceneIdxWithSpacedName),
|
||||
},
|
||||
Movies: []models.MoviesScenes{
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: invalidID,
|
||||
SceneIndex: &sceneIndex,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -456,6 +477,12 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
||||
t.Errorf("sceneQueryBuilder.Find() error = %v", err)
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, copy, s); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(copy, *s)
|
||||
})
|
||||
}
|
||||
@@ -571,10 +598,10 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithScene]},
|
||||
TagIDs: []int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]},
|
||||
PerformerIDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
|
||||
Movies: []models.MoviesScenes{
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithScene], tagIDs[tagIdx1WithDupName]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: movieIDs[movieIdxWithScene],
|
||||
SceneIndex: &sceneIndex,
|
||||
@@ -583,8 +610,8 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
MovieID: movieIDs[movieIdxWithStudio],
|
||||
SceneIndex: &sceneIndex2,
|
||||
},
|
||||
},
|
||||
StashIDs: []models.StashID{
|
||||
}),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{
|
||||
{
|
||||
StashID: stashID1,
|
||||
Endpoint: endpoint1,
|
||||
@@ -593,7 +620,7 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
StashID: stashID2,
|
||||
Endpoint: endpoint2,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -606,11 +633,11 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
Files: []*file.VideoFile{
|
||||
makeSceneFile(sceneIdxWithSpacedName),
|
||||
},
|
||||
GalleryIDs: []int{},
|
||||
TagIDs: []int{},
|
||||
PerformerIDs: []int{},
|
||||
Movies: []models.MoviesScenes{},
|
||||
StashIDs: []models.StashID{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
TagIDs: models.NewRelatedIDs([]int{}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{}),
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -641,6 +668,12 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
// ignore file ids
|
||||
clearSceneFileIDs(got)
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, *got)
|
||||
|
||||
s, err := qb.Find(ctx, tt.id)
|
||||
@@ -651,6 +684,12 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
||||
// ignore file ids
|
||||
clearSceneFileIDs(s)
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, tt.want, s); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, *s)
|
||||
})
|
||||
}
|
||||
@@ -705,10 +744,10 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
GalleryIDs: append(indexesToIDs(galleryIDs, sceneGalleries[sceneIdxWithGallery]),
|
||||
GalleryIDs: models.NewRelatedIDs(append(indexesToIDs(galleryIDs, sceneGalleries[sceneIdxWithGallery]),
|
||||
galleryIDs[galleryIdx1WithImage],
|
||||
galleryIDs[galleryIdx1WithPerformer],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -722,10 +761,10 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
TagIDs: append(indexesToIDs(tagIDs, sceneTags[sceneIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(append(indexesToIDs(tagIDs, sceneTags[sceneIdxWithTwoTags]),
|
||||
tagIDs[tagIdx1WithDupName],
|
||||
tagIDs[tagIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -739,10 +778,10 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
PerformerIDs: append(indexesToIDs(performerIDs, scenePerformers[sceneIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(append(indexesToIDs(performerIDs, scenePerformers[sceneIdxWithTwoPerformers]),
|
||||
performerIDs[performerIdx1WithDupName],
|
||||
performerIDs[performerIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -756,11 +795,11 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
Movies: append([]models.MoviesScenes{
|
||||
Movies: models.NewRelatedMovies(append([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: indexesToIDs(movieIDs, sceneMovies[sceneIdxWithMovie])[0],
|
||||
},
|
||||
}, movieScenes...),
|
||||
}, movieScenes...)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -774,7 +813,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
StashIDs: append([]models.StashID{sceneStashID(sceneIdxWithSpacedName)}, stashIDs...),
|
||||
StashIDs: models.NewRelatedStashIDs(append([]models.StashID{sceneStashID(sceneIdxWithSpacedName)}, stashIDs...)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -788,9 +827,9 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
GalleryIDs: append(indexesToIDs(galleryIDs, sceneGalleries[sceneIdxWithGallery]),
|
||||
GalleryIDs: models.NewRelatedIDs(append(indexesToIDs(galleryIDs, sceneGalleries[sceneIdxWithGallery]),
|
||||
galleryIDs[galleryIdx1WithPerformer],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -804,9 +843,9 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
TagIDs: append(indexesToIDs(tagIDs, sceneTags[sceneIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(append(indexesToIDs(tagIDs, sceneTags[sceneIdxWithTwoTags]),
|
||||
tagIDs[tagIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -820,9 +859,9 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
PerformerIDs: append(indexesToIDs(performerIDs, scenePerformers[sceneIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(append(indexesToIDs(performerIDs, scenePerformers[sceneIdxWithTwoPerformers]),
|
||||
performerIDs[performerIdx1WithGallery],
|
||||
),
|
||||
)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -843,11 +882,11 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
Movies: append([]models.MoviesScenes{
|
||||
Movies: models.NewRelatedMovies(append([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: indexesToIDs(movieIDs, sceneMovies[sceneIdxWithMovie])[0],
|
||||
},
|
||||
}, movieScenes...),
|
||||
}, movieScenes...)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -863,7 +902,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
StashIDs: []models.StashID{sceneStashID(sceneIdxWithSpacedName)},
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{sceneStashID(sceneIdxWithSpacedName)}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -929,7 +968,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
GalleryIDs: []int{},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -943,7 +982,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
TagIDs: []int{tagIDs[tagIdx2WithScene]},
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx2WithScene]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -957,7 +996,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
PerformerIDs: []int{performerIDs[performerIdx2WithScene]},
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx2WithScene]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -975,7 +1014,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
Movies: []models.MoviesScenes{},
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -989,7 +1028,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
StashIDs: []models.StashID{},
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -1003,7 +1042,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
GalleryIDs: []int{galleryIDs[galleryIdxWithScene]},
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -1017,7 +1056,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
TagIDs: indexesToIDs(tagIDs, sceneTags[sceneIdxWithTwoTags]),
|
||||
TagIDs: models.NewRelatedIDs(indexesToIDs(tagIDs, sceneTags[sceneIdxWithTwoTags])),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -1031,7 +1070,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
PerformerIDs: indexesToIDs(performerIDs, scenePerformers[sceneIdxWithTwoPerformers]),
|
||||
PerformerIDs: models.NewRelatedIDs(indexesToIDs(performerIDs, scenePerformers[sceneIdxWithTwoPerformers])),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -1049,11 +1088,11 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
Movies: []models.MoviesScenes{
|
||||
Movies: models.NewRelatedMovies([]models.MoviesScenes{
|
||||
{
|
||||
MovieID: indexesToIDs(movieIDs, sceneMovies[sceneIdxWithMovie])[0],
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -1067,7 +1106,7 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
},
|
||||
},
|
||||
models.Scene{
|
||||
StashIDs: []models.StashID{sceneStashID(sceneIdxWithGallery)},
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{sceneStashID(sceneIdxWithGallery)}),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -1094,6 +1133,16 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
|
||||
t.Errorf("sceneQueryBuilder.Find() error = %v", err)
|
||||
}
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
if err := loadSceneRelationships(ctx, tt.want, s); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// only compare fields that were in the partial
|
||||
if tt.partial.PerformerIDs != nil {
|
||||
assert.Equal(tt.want.PerformerIDs, got.PerformerIDs)
|
||||
@@ -1353,6 +1402,12 @@ func Test_sceneQueryBuilder_Find(t *testing.T) {
|
||||
|
||||
if got != nil {
|
||||
clearSceneFileIDs(got)
|
||||
|
||||
// load relationships
|
||||
if err := loadSceneRelationships(ctx, *tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1362,6 +1417,21 @@ func Test_sceneQueryBuilder_Find(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func postFindScenes(ctx context.Context, want []*models.Scene, got []*models.Scene) error {
|
||||
for i, s := range got {
|
||||
clearSceneFileIDs(s)
|
||||
|
||||
// load relationships
|
||||
if i < len(want) {
|
||||
if err := loadSceneRelationships(ctx, *want[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_sceneQueryBuilder_FindMany(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1404,8 +1474,9 @@ func Test_sceneQueryBuilder_FindMany(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, s := range got {
|
||||
clearSceneFileIDs(s)
|
||||
if err := postFindScenes(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1474,8 +1545,9 @@ func Test_sceneQueryBuilder_FindByChecksum(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, s := range got {
|
||||
clearSceneFileIDs(s)
|
||||
if err := postFindScenes(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1546,8 +1618,9 @@ func Test_sceneQueryBuilder_FindByOSHash(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, s := range got {
|
||||
clearSceneFileIDs(s)
|
||||
if err := postFindScenes(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
@@ -1620,8 +1693,9 @@ func Test_sceneQueryBuilder_FindByPath(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, s := range got {
|
||||
clearSceneFileIDs(s)
|
||||
if err := postFindScenes(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -1664,8 +1738,9 @@ func Test_sceneQueryBuilder_FindByGalleryID(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, s := range got {
|
||||
clearSceneFileIDs(s)
|
||||
if err := postFindScenes(ctx, tt.want, got); err != nil {
|
||||
t.Errorf("loadSceneRelationships() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
@@ -3539,7 +3614,11 @@ func verifyScenesTagCount(t *testing.T, tagCountCriterion models.IntCriterionInp
|
||||
assert.Greater(t, len(scenes), 0)
|
||||
|
||||
for _, scene := range scenes {
|
||||
verifyInt(t, len(scene.TagIDs), tagCountCriterion)
|
||||
if err := scene.LoadTagIDs(ctx, sqb); err != nil {
|
||||
t.Errorf("scene.LoadTagIDs() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
verifyInt(t, len(scene.TagIDs.List()), tagCountCriterion)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -3576,7 +3655,12 @@ func verifyScenesPerformerCount(t *testing.T, performerCountCriterion models.Int
|
||||
assert.Greater(t, len(scenes), 0)
|
||||
|
||||
for _, scene := range scenes {
|
||||
verifyInt(t, len(scene.PerformerIDs), performerCountCriterion)
|
||||
if err := scene.LoadPerformerIDs(ctx, sqb); err != nil {
|
||||
t.Errorf("scene.LoadPerformerIDs() error = %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
verifyInt(t, len(scene.PerformerIDs.List()), performerCountCriterion)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -3776,6 +3860,10 @@ func TestSceneStashIDs(t *testing.T) {
|
||||
return fmt.Errorf("Error creating scene: %s", err.Error())
|
||||
}
|
||||
|
||||
if err := scene.LoadStashIDs(ctx, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
testSceneStashIDs(ctx, t, scene)
|
||||
return nil
|
||||
}); err != nil {
|
||||
@@ -3785,7 +3873,7 @@ func TestSceneStashIDs(t *testing.T) {
|
||||
|
||||
func testSceneStashIDs(ctx context.Context, t *testing.T, s *models.Scene) {
|
||||
// ensure no stash IDs to begin with
|
||||
assert.Len(t, s.StashIDs, 0)
|
||||
assert.Len(t, s.StashIDs.List(), 0)
|
||||
|
||||
// add stash ids
|
||||
const stashIDStr = "stashID"
|
||||
@@ -3809,7 +3897,12 @@ func testSceneStashIDs(ctx context.Context, t *testing.T, s *models.Scene) {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
assert.Equal(t, []models.StashID{stashID}, s.StashIDs)
|
||||
if err := s.LoadStashIDs(ctx, qb); err != nil {
|
||||
t.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, []models.StashID{stashID}, s.StashIDs.List())
|
||||
|
||||
// remove stash ids and ensure was updated
|
||||
s, err = qb.UpdatePartial(ctx, s.ID, models.ScenePartial{
|
||||
@@ -3822,7 +3915,12 @@ func testSceneStashIDs(ctx context.Context, t *testing.T, s *models.Scene) {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
assert.Len(t, s.StashIDs, 0)
|
||||
if err := s.LoadStashIDs(ctx, qb); err != nil {
|
||||
t.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
assert.Len(t, s.StashIDs.List(), 0)
|
||||
}
|
||||
|
||||
func TestSceneQueryQTrim(t *testing.T) {
|
||||
|
||||
@@ -975,13 +975,13 @@ func makeScene(i int) *models.Scene {
|
||||
OCounter: getOCounter(i),
|
||||
Date: getObjectDateObject(i),
|
||||
StudioID: studioID,
|
||||
GalleryIDs: gids,
|
||||
PerformerIDs: pids,
|
||||
TagIDs: tids,
|
||||
Movies: movies,
|
||||
StashIDs: []models.StashID{
|
||||
GalleryIDs: models.NewRelatedIDs(gids),
|
||||
PerformerIDs: models.NewRelatedIDs(pids),
|
||||
TagIDs: models.NewRelatedIDs(tids),
|
||||
Movies: models.NewRelatedMovies(movies),
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{
|
||||
sceneStashID(i),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1051,9 +1051,9 @@ func makeImage(i int) *models.Image {
|
||||
Rating: getIntPtr(getRating(i)),
|
||||
OCounter: getOCounter(i),
|
||||
StudioID: studioID,
|
||||
GalleryIDs: gids,
|
||||
PerformerIDs: pids,
|
||||
TagIDs: tids,
|
||||
GalleryIDs: models.NewRelatedIDs(gids),
|
||||
PerformerIDs: models.NewRelatedIDs(pids),
|
||||
TagIDs: models.NewRelatedIDs(tids),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,12 +1135,12 @@ func makeGallery(i int, includeScenes bool) *models.Gallery {
|
||||
Rating: getIntPtr(getRating(i)),
|
||||
Date: getObjectDateObject(i),
|
||||
StudioID: studioID,
|
||||
PerformerIDs: pids,
|
||||
TagIDs: tids,
|
||||
PerformerIDs: models.NewRelatedIDs(pids),
|
||||
TagIDs: models.NewRelatedIDs(tids),
|
||||
}
|
||||
|
||||
if includeScenes {
|
||||
ret.SceneIDs = indexesToIDs(sceneIDs, sceneGalleries.reverseLookup(i))
|
||||
ret.SceneIDs = models.NewRelatedIDs(indexesToIDs(sceneIDs, sceneGalleries.reverseLookup(i)))
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
type stashIDReaderWriter interface {
|
||||
GetStashIDs(ctx context.Context, performerID int) ([]*models.StashID, error)
|
||||
UpdateStashIDs(ctx context.Context, performerID int, stashIDs []*models.StashID) error
|
||||
GetStashIDs(ctx context.Context, performerID int) ([]models.StashID, error)
|
||||
UpdateStashIDs(ctx context.Context, performerID int, stashIDs []models.StashID) error
|
||||
}
|
||||
|
||||
func testStashIDReaderWriter(ctx context.Context, t *testing.T, r stashIDReaderWriter, id int) {
|
||||
@@ -26,25 +26,25 @@ func testStashIDReaderWriter(ctx context.Context, t *testing.T, r stashIDReaderW
|
||||
// add stash ids
|
||||
const stashIDStr = "stashID"
|
||||
const endpoint = "endpoint"
|
||||
stashID := &models.StashID{
|
||||
stashID := models.StashID{
|
||||
StashID: stashIDStr,
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
|
||||
// update stash ids and ensure was updated
|
||||
if err := r.UpdateStashIDs(ctx, id, []*models.StashID{stashID}); err != nil {
|
||||
if err := r.UpdateStashIDs(ctx, id, []models.StashID{stashID}); err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
testStashIDs(ctx, t, r, id, []*models.StashID{stashID})
|
||||
testStashIDs(ctx, t, r, id, []models.StashID{stashID})
|
||||
|
||||
// update non-existing id - should return error
|
||||
if err := r.UpdateStashIDs(ctx, -1, []*models.StashID{stashID}); err == nil {
|
||||
if err := r.UpdateStashIDs(ctx, -1, []models.StashID{stashID}); err == nil {
|
||||
t.Error("expected error when updating non-existing id")
|
||||
}
|
||||
|
||||
// remove stash ids and ensure was updated
|
||||
if err := r.UpdateStashIDs(ctx, id, []*models.StashID{}); err != nil {
|
||||
if err := r.UpdateStashIDs(ctx, id, []models.StashID{}); err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func testNoStashIDs(ctx context.Context, t *testing.T, r stashIDReaderWriter, id
|
||||
assert.Len(t, stashIDs, 0)
|
||||
}
|
||||
|
||||
func testStashIDs(ctx context.Context, t *testing.T, r stashIDReaderWriter, id int, expected []*models.StashID) {
|
||||
func testStashIDs(ctx context.Context, t *testing.T, r stashIDReaderWriter, id int, expected []models.StashID) {
|
||||
t.Helper()
|
||||
stashIDs, err := r.GetStashIDs(ctx, id)
|
||||
if err != nil {
|
||||
|
||||
@@ -7,7 +7,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
)
|
||||
|
||||
const studioTable = "studios"
|
||||
@@ -76,21 +79,45 @@ func (qb *studioQueryBuilder) Find(ctx context.Context, id int) (*models.Studio,
|
||||
}
|
||||
|
||||
func (qb *studioQueryBuilder) FindMany(ctx context.Context, ids []int) ([]*models.Studio, error) {
|
||||
var studios []*models.Studio
|
||||
for _, id := range ids {
|
||||
studio, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if studio == nil {
|
||||
return nil, fmt.Errorf("studio with id %d not found", id)
|
||||
}
|
||||
|
||||
studios = append(studios, studio)
|
||||
tableMgr := studioTableMgr
|
||||
q := goqu.Select("*").From(tableMgr.table).Where(tableMgr.byIDInts(ids...))
|
||||
unsorted, err := qb.getMany(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return studios, nil
|
||||
ret := make([]*models.Studio, len(ids))
|
||||
|
||||
for _, s := range unsorted {
|
||||
i := intslice.IntIndex(ids, s.ID)
|
||||
ret[i] = s
|
||||
}
|
||||
|
||||
for i := range ret {
|
||||
if ret[i] == nil {
|
||||
return nil, fmt.Errorf("studio with id %d not found", ids[i])
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *studioQueryBuilder) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*models.Studio, error) {
|
||||
const single = false
|
||||
var ret []*models.Studio
|
||||
if err := queryFunc(ctx, q, single, func(r *sqlx.Rows) error {
|
||||
var f models.Studio
|
||||
if err := r.StructScan(&f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, &f)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *studioQueryBuilder) FindChildren(ctx context.Context, id int) ([]*models.Studio, error) {
|
||||
@@ -258,14 +285,9 @@ func (qb *studioQueryBuilder) Query(ctx context.Context, studioFilter *models.St
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var studios []*models.Studio
|
||||
for _, id := range idsResult {
|
||||
studio, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
studios = append(studios, studio)
|
||||
studios, err := qb.FindMany(ctx, idsResult)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return studios, countResult, nil
|
||||
@@ -425,11 +447,11 @@ func (qb *studioQueryBuilder) stashIDRepository() *stashIDRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *studioQueryBuilder) GetStashIDs(ctx context.Context, studioID int) ([]*models.StashID, error) {
|
||||
func (qb *studioQueryBuilder) GetStashIDs(ctx context.Context, studioID int) ([]models.StashID, error) {
|
||||
return qb.stashIDRepository().get(ctx, studioID)
|
||||
}
|
||||
|
||||
func (qb *studioQueryBuilder) UpdateStashIDs(ctx context.Context, studioID int, stashIDs []*models.StashID) error {
|
||||
func (qb *studioQueryBuilder) UpdateStashIDs(ctx context.Context, studioID int, stashIDs []models.StashID) error {
|
||||
return qb.stashIDRepository().replace(ctx, studioID, stashIDs)
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,14 @@ func (t *table) byID(id interface{}) exp.Expression {
|
||||
return t.idColumn.Eq(id)
|
||||
}
|
||||
|
||||
func (t *table) byIDInts(ids ...int) exp.Expression {
|
||||
ii := make([]interface{}, len(ids))
|
||||
for i, id := range ids {
|
||||
ii[i] = id
|
||||
}
|
||||
return t.idColumn.In(ii...)
|
||||
}
|
||||
|
||||
func (t *table) idExists(ctx context.Context, id interface{}) (bool, error) {
|
||||
q := dialect.Select(goqu.COUNT("*")).From(t.table).Where(t.byID(id))
|
||||
|
||||
|
||||
@@ -174,3 +174,31 @@ var (
|
||||
idColumn: goqu.T(fingerprintTable).Col(idColumn),
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
performerTableMgr = &table{
|
||||
table: goqu.T(performerTable),
|
||||
idColumn: goqu.T(performerTable).Col(idColumn),
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
studioTableMgr = &table{
|
||||
table: goqu.T(studioTable),
|
||||
idColumn: goqu.T(studioTable).Col(idColumn),
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
tagTableMgr = &table{
|
||||
table: goqu.T(tagTable),
|
||||
idColumn: goqu.T(tagTable).Col(idColumn),
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
movieTableMgr = &table{
|
||||
table: goqu.T(movieTable),
|
||||
idColumn: goqu.T(movieTable).Col(idColumn),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -7,7 +7,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/doug-martin/goqu/v9"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
)
|
||||
|
||||
const tagTable = "tags"
|
||||
@@ -94,21 +97,45 @@ func (qb *tagQueryBuilder) Find(ctx context.Context, id int) (*models.Tag, error
|
||||
}
|
||||
|
||||
func (qb *tagQueryBuilder) FindMany(ctx context.Context, ids []int) ([]*models.Tag, error) {
|
||||
var tags []*models.Tag
|
||||
for _, id := range ids {
|
||||
tag, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tag == nil {
|
||||
return nil, fmt.Errorf("tag with id %d not found", id)
|
||||
}
|
||||
|
||||
tags = append(tags, tag)
|
||||
tableMgr := tagTableMgr
|
||||
q := goqu.Select("*").From(tableMgr.table).Where(tableMgr.byIDInts(ids...))
|
||||
unsorted, err := qb.getMany(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tags, nil
|
||||
ret := make([]*models.Tag, len(ids))
|
||||
|
||||
for _, s := range unsorted {
|
||||
i := intslice.IntIndex(ids, s.ID)
|
||||
ret[i] = s
|
||||
}
|
||||
|
||||
for i := range ret {
|
||||
if ret[i] == nil {
|
||||
return nil, fmt.Errorf("tag with id %d not found", ids[i])
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *tagQueryBuilder) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*models.Tag, error) {
|
||||
const single = false
|
||||
var ret []*models.Tag
|
||||
if err := queryFunc(ctx, q, single, func(r *sqlx.Rows) error {
|
||||
var f models.Tag
|
||||
if err := r.StructScan(&f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, &f)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *tagQueryBuilder) FindBySceneID(ctx context.Context, sceneID int) ([]*models.Tag, error) {
|
||||
@@ -343,13 +370,9 @@ func (qb *tagQueryBuilder) Query(ctx context.Context, tagFilter *models.TagFilte
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var tags []*models.Tag
|
||||
for _, id := range idsResult {
|
||||
tag, err := qb.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
tags = append(tags, tag)
|
||||
tags, err := qb.FindMany(ctx, idsResult)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return tags, countResult, nil
|
||||
|
||||
@@ -961,7 +961,10 @@ func TestTagMerge(t *testing.T) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sceneTagIDs := s.TagIDs
|
||||
if err := s.LoadTagIDs(ctx, db.Scene); err != nil {
|
||||
return err
|
||||
}
|
||||
sceneTagIDs := s.TagIDs.List()
|
||||
|
||||
assert.Contains(sceneTagIDs, destID)
|
||||
|
||||
@@ -993,8 +996,12 @@ func TestTagMerge(t *testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.LoadTagIDs(ctx, db.Gallery); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ensure gallery points to new tag
|
||||
assert.Contains(g.TagIDs, destID)
|
||||
assert.Contains(g.TagIDs.List(), destID)
|
||||
|
||||
// ensure performer points to new tag
|
||||
performerTagIDs, err := sqlite.PerformerReaderWriter.GetTagIDs(ctx, performerIDs[performerIdxWithTwoTags])
|
||||
|
||||
Reference in New Issue
Block a user