From 501ed7c2c28f5025d5b414af7910db2684b0481c Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Thu, 16 Sep 2021 20:41:07 +1000 Subject: [PATCH] Make hierarchical criterion depth input optional (#1733) --- graphql/schema/types/filters.graphql | 2 +- pkg/dlna/cds.go | 2 -- pkg/gallery/query.go | 2 -- pkg/image/query.go | 2 -- pkg/sqlite/filter.go | 18 ++++++++++++------ pkg/sqlite/gallery_test.go | 19 +++++++------------ pkg/sqlite/image_test.go | 19 +++++++------------ pkg/sqlite/movies_test.go | 2 -- pkg/sqlite/performer_test.go | 3 --- pkg/sqlite/scene_test.go | 18 ++++++------------ pkg/sqlite/studio_test.go | 2 -- 11 files changed, 33 insertions(+), 56 deletions(-) diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 36f7b93bc..ccaa27503 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -365,7 +365,7 @@ input GenderCriterionInput { input HierarchicalMultiCriterionInput { value: [ID!] modifier: CriterionModifier! - depth: Int! + depth: Int } enum FilterMode { diff --git a/pkg/dlna/cds.go b/pkg/dlna/cds.go index 79a80ab51..d23660d0b 100644 --- a/pkg/dlna/cds.go +++ b/pkg/dlna/cds.go @@ -533,7 +533,6 @@ func (me *contentDirectoryService) getStudioScenes(paths []string, host string) Studios: &models.HierarchicalMultiCriterionInput{ Modifier: models.CriterionModifierIncludes, Value: []string{paths[0]}, - Depth: 0, }, } @@ -573,7 +572,6 @@ func (me *contentDirectoryService) getTagScenes(paths []string, host string) []i Tags: &models.HierarchicalMultiCriterionInput{ Modifier: models.CriterionModifierIncludes, Value: []string{paths[0]}, - Depth: 0, }, } diff --git a/pkg/gallery/query.go b/pkg/gallery/query.go index a7fbed856..f15e480f2 100644 --- a/pkg/gallery/query.go +++ b/pkg/gallery/query.go @@ -22,7 +22,6 @@ func CountByStudioID(r models.GalleryReader, id int) (int, error) { Studios: &models.HierarchicalMultiCriterionInput{ Value: []string{strconv.Itoa(id)}, Modifier: models.CriterionModifierIncludes, - Depth: 0, }, } @@ -34,7 +33,6 @@ func CountByTagID(r models.GalleryReader, id int) (int, error) { Tags: &models.HierarchicalMultiCriterionInput{ Value: []string{strconv.Itoa(id)}, Modifier: models.CriterionModifierIncludes, - Depth: 0, }, } diff --git a/pkg/image/query.go b/pkg/image/query.go index eca6d49a4..7b2dac990 100644 --- a/pkg/image/query.go +++ b/pkg/image/query.go @@ -22,7 +22,6 @@ func CountByStudioID(r models.ImageReader, id int) (int, error) { Studios: &models.HierarchicalMultiCriterionInput{ Value: []string{strconv.Itoa(id)}, Modifier: models.CriterionModifierIncludes, - Depth: 0, }, } @@ -34,7 +33,6 @@ func CountByTagID(r models.ImageReader, id int) (int, error) { Tags: &models.HierarchicalMultiCriterionInput{ Value: []string{strconv.Itoa(id)}, Modifier: models.CriterionModifierIncludes, - Depth: 0, }, } diff --git a/pkg/sqlite/filter.go b/pkg/sqlite/filter.go index 0d47c2fb2..d29647cf9 100644 --- a/pkg/sqlite/filter.go +++ b/pkg/sqlite/filter.go @@ -3,11 +3,12 @@ package sqlite import ( "errors" "fmt" - "github.com/stashapp/stash/pkg/logger" "regexp" "strconv" "strings" + "github.com/stashapp/stash/pkg/logger" + "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/utils" ) @@ -534,10 +535,15 @@ type hierarchicalMultiCriterionHandlerBuilder struct { relationsTable string } -func getHierarchicalValues(tx dbi, values []string, table, relationsTable, parentFK string, depth int) string { +func getHierarchicalValues(tx dbi, values []string, table, relationsTable, parentFK string, depth *int) string { var args []interface{} - if depth == 0 { + depthVal := 0 + if depth != nil { + depthVal = *depth + } + + if depthVal == 0 { valid := true var valuesClauses []string for _, value := range values { @@ -563,8 +569,8 @@ func getHierarchicalValues(tx dbi, values []string, table, relationsTable, paren inCount := len(args) var depthCondition string - if depth != -1 { - depthCondition = fmt.Sprintf("WHERE depth < %d", depth) + if depthVal != -1 { + depthCondition = fmt.Sprintf("WHERE depth < %d", depthVal) } withClauseMap := utils.StrFormatMap{ @@ -587,7 +593,7 @@ INNER JOIN items as p ON c.{parentFK} = p.item_id `, withClauseMap) } - if depth != 0 { + if depthVal != 0 { withClauseMap["unionClause"] = utils.StrFormat(` UNION {recursiveSelect} {depthCondition} `, withClauseMap) diff --git a/pkg/sqlite/gallery_test.go b/pkg/sqlite/gallery_test.go index 4ba755b00..d07907156 100644 --- a/pkg/sqlite/gallery_test.go +++ b/pkg/sqlite/gallery_test.go @@ -627,7 +627,6 @@ func TestGalleryQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithGallery]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } galleryFilter := models.GalleryFilterType{ @@ -648,7 +647,6 @@ func TestGalleryQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithGallery]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } galleries = queryGallery(t, sqb, &galleryFilter, nil) @@ -661,7 +659,6 @@ func TestGalleryQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithGallery]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getGalleryStringValue(galleryIdxWithTwoTags, titleField) @@ -684,7 +681,6 @@ func TestGalleryQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithGallery]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } galleryFilter := models.GalleryFilterType{ @@ -703,7 +699,6 @@ func TestGalleryQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithGallery]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getGalleryStringValue(galleryIdxWithStudio, titleField) @@ -721,12 +716,13 @@ func TestGalleryQueryStudio(t *testing.T) { func TestGalleryQueryStudioDepth(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() + depth := 2 studioCriterion := models.HierarchicalMultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGrandChild]), }, Modifier: models.CriterionModifierIncludes, - Depth: 2, + Depth: &depth, } galleryFilter := models.GalleryFilterType{ @@ -736,7 +732,7 @@ func TestGalleryQueryStudioDepth(t *testing.T) { galleries := queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 1) - studioCriterion.Depth = 1 + depth = 1 galleries = queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 0) @@ -748,12 +744,14 @@ func TestGalleryQueryStudioDepth(t *testing.T) { // ensure id is correct assert.Equal(t, galleryIDs[galleryIdxWithGrandChildStudio], galleries[0].ID) + depth = 2 + studioCriterion = models.HierarchicalMultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGrandChild]), }, Modifier: models.CriterionModifierExcludes, - Depth: 2, + Depth: &depth, } q := getGalleryStringValue(galleryIdxWithGrandChildStudio, pathField) @@ -764,7 +762,7 @@ func TestGalleryQueryStudioDepth(t *testing.T) { galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) - studioCriterion.Depth = 1 + depth = 1 galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 1) @@ -785,7 +783,6 @@ func TestGalleryQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } galleryFilter := models.GalleryFilterType{ @@ -806,7 +803,6 @@ func TestGalleryQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithPerformer]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } galleries = queryGallery(t, sqb, &galleryFilter, nil) @@ -819,7 +815,6 @@ func TestGalleryQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getGalleryStringValue(galleryIdxWithPerformerTwoTags, titleField) diff --git a/pkg/sqlite/image_test.go b/pkg/sqlite/image_test.go index 02e077c8d..59802e0d8 100644 --- a/pkg/sqlite/image_test.go +++ b/pkg/sqlite/image_test.go @@ -728,7 +728,6 @@ func TestImageQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithImage]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } imageFilter := models.ImageFilterType{ @@ -753,7 +752,6 @@ func TestImageQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithImage]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } images, _, err = sqb.Query(&imageFilter, nil) @@ -769,7 +767,6 @@ func TestImageQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithImage]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getImageStringValue(imageIdxWithTwoTags, titleField) @@ -795,7 +792,6 @@ func TestImageQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithImage]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } imageFilter := models.ImageFilterType{ @@ -817,7 +813,6 @@ func TestImageQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithImage]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getImageStringValue(imageIdxWithStudio, titleField) @@ -838,12 +833,13 @@ func TestImageQueryStudio(t *testing.T) { func TestImageQueryStudioDepth(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Image() + depth := 2 studioCriterion := models.HierarchicalMultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGrandChild]), }, Modifier: models.CriterionModifierIncludes, - Depth: 2, + Depth: &depth, } imageFilter := models.ImageFilterType{ @@ -853,7 +849,7 @@ func TestImageQueryStudioDepth(t *testing.T) { images := queryImages(t, sqb, &imageFilter, nil) assert.Len(t, images, 1) - studioCriterion.Depth = 1 + depth = 1 images = queryImages(t, sqb, &imageFilter, nil) assert.Len(t, images, 0) @@ -865,12 +861,14 @@ func TestImageQueryStudioDepth(t *testing.T) { // ensure id is correct assert.Equal(t, imageIDs[imageIdxWithGrandChildStudio], images[0].ID) + depth = 2 + studioCriterion = models.HierarchicalMultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGrandChild]), }, Modifier: models.CriterionModifierExcludes, - Depth: 2, + Depth: &depth, } q := getImageStringValue(imageIdxWithGrandChildStudio, titleField) @@ -881,7 +879,7 @@ func TestImageQueryStudioDepth(t *testing.T) { images = queryImages(t, sqb, &imageFilter, &findFilter) assert.Len(t, images, 0) - studioCriterion.Depth = 1 + depth = 1 images = queryImages(t, sqb, &imageFilter, &findFilter) assert.Len(t, images, 1) @@ -911,7 +909,6 @@ func TestImageQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } imageFilter := models.ImageFilterType{ @@ -932,7 +929,6 @@ func TestImageQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithPerformer]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } images = queryImages(t, sqb, &imageFilter, nil) @@ -945,7 +941,6 @@ func TestImageQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getImageStringValue(imageIdxWithPerformerTwoTags, titleField) diff --git a/pkg/sqlite/movies_test.go b/pkg/sqlite/movies_test.go index a81cc4586..681c9fa09 100644 --- a/pkg/sqlite/movies_test.go +++ b/pkg/sqlite/movies_test.go @@ -82,7 +82,6 @@ func TestMovieQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithMovie]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } movieFilter := models.MovieFilterType{ @@ -104,7 +103,6 @@ func TestMovieQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithMovie]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getMovieStringValue(movieIdxWithStudio, titleField) diff --git a/pkg/sqlite/performer_test.go b/pkg/sqlite/performer_test.go index dd61c6f99..829016d57 100644 --- a/pkg/sqlite/performer_test.go +++ b/pkg/sqlite/performer_test.go @@ -506,7 +506,6 @@ func TestPerformerQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } performerFilter := models.PerformerFilterType{ @@ -526,7 +525,6 @@ func TestPerformerQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithPerformer]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } performers = queryPerformers(t, sqb, &performerFilter, nil) @@ -539,7 +537,6 @@ func TestPerformerQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getSceneStringValue(performerIdxWithTwoTags, titleField) diff --git a/pkg/sqlite/scene_test.go b/pkg/sqlite/scene_test.go index aa895b8b7..48790d1ae 100644 --- a/pkg/sqlite/scene_test.go +++ b/pkg/sqlite/scene_test.go @@ -1040,7 +1040,6 @@ func TestSceneQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithScene]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } sceneFilter := models.SceneFilterType{ @@ -1061,7 +1060,6 @@ func TestSceneQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithScene]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } scenes = queryScene(t, sqb, &sceneFilter, nil) @@ -1074,7 +1072,6 @@ func TestSceneQueryTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithScene]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getSceneStringValue(sceneIdxWithTwoTags, titleField) @@ -1098,7 +1095,6 @@ func TestSceneQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } sceneFilter := models.SceneFilterType{ @@ -1119,7 +1115,6 @@ func TestSceneQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx2WithPerformer]), }, Modifier: models.CriterionModifierIncludesAll, - Depth: 0, } scenes = queryScene(t, sqb, &sceneFilter, nil) @@ -1132,7 +1127,6 @@ func TestSceneQueryPerformerTags(t *testing.T) { strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getSceneStringValue(sceneIdxWithPerformerTwoTags, titleField) @@ -1155,7 +1149,6 @@ func TestSceneQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithScene]), }, Modifier: models.CriterionModifierIncludes, - Depth: 0, } sceneFilter := models.SceneFilterType{ @@ -1174,7 +1167,6 @@ func TestSceneQueryStudio(t *testing.T) { strconv.Itoa(studioIDs[studioIdxWithScene]), }, Modifier: models.CriterionModifierExcludes, - Depth: 0, } q := getSceneStringValue(sceneIdxWithStudio, titleField) @@ -1192,12 +1184,13 @@ func TestSceneQueryStudio(t *testing.T) { func TestSceneQueryStudioDepth(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Scene() + depth := 2 studioCriterion := models.HierarchicalMultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGrandChild]), }, Modifier: models.CriterionModifierIncludes, - Depth: 2, + Depth: &depth, } sceneFilter := models.SceneFilterType{ @@ -1207,7 +1200,7 @@ func TestSceneQueryStudioDepth(t *testing.T) { scenes := queryScene(t, sqb, &sceneFilter, nil) assert.Len(t, scenes, 1) - studioCriterion.Depth = 1 + depth = 1 scenes = queryScene(t, sqb, &sceneFilter, nil) assert.Len(t, scenes, 0) @@ -1218,13 +1211,14 @@ func TestSceneQueryStudioDepth(t *testing.T) { // ensure id is correct assert.Equal(t, sceneIDs[sceneIdxWithGrandChildStudio], scenes[0].ID) + depth = 2 studioCriterion = models.HierarchicalMultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGrandChild]), }, Modifier: models.CriterionModifierExcludes, - Depth: 2, + Depth: &depth, } q := getSceneStringValue(sceneIdxWithGrandChildStudio, titleField) @@ -1235,7 +1229,7 @@ func TestSceneQueryStudioDepth(t *testing.T) { scenes = queryScene(t, sqb, &sceneFilter, &findFilter) assert.Len(t, scenes, 0) - studioCriterion.Depth = 1 + depth = 1 scenes = queryScene(t, sqb, &sceneFilter, &findFilter) assert.Len(t, scenes, 1) diff --git a/pkg/sqlite/studio_test.go b/pkg/sqlite/studio_test.go index 8ac08d603..bb3dd3e18 100644 --- a/pkg/sqlite/studio_test.go +++ b/pkg/sqlite/studio_test.go @@ -511,7 +511,6 @@ func verifyStudiosImageCount(t *testing.T, imageCountCriterion models.IntCriteri Studios: &models.HierarchicalMultiCriterionInput{ Value: []string{strconv.Itoa(studio.ID)}, Modifier: models.CriterionModifierIncludes, - Depth: 0, }, }, &models.FindFilterType{ PerPage: &pp, @@ -562,7 +561,6 @@ func verifyStudiosGalleryCount(t *testing.T, galleryCountCriterion models.IntCri Studios: &models.HierarchicalMultiCriterionInput{ Value: []string{strconv.Itoa(studio.ID)}, Modifier: models.CriterionModifierIncludes, - Depth: 0, }, }, &models.FindFilterType{ PerPage: &pp,