mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Make hierarchical criterion depth input optional (#1733)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user