mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Fix excludes handling in performer studio filter (#6413)
This commit is contained in:
@@ -447,7 +447,7 @@ func (qb *performerFilterHandler) studiosCriterionHandler(studios *models.Hierar
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(studios.Value) == 0 {
|
if len(studios.Value) == 0 && len(studios.Excludes) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,6 +464,7 @@ func (qb *performerFilterHandler) studiosCriterionHandler(studios *models.Hierar
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(studios.Value) > 0 {
|
||||||
const derivedPerformerStudioTable = "performer_studio"
|
const derivedPerformerStudioTable = "performer_studio"
|
||||||
valuesClause, err := getHierarchicalValues(ctx, studios.Value, studioTable, "", "parent_id", "child_id", studios.Depth)
|
valuesClause, err := getHierarchicalValues(ctx, studios.Value, studioTable, "", "parent_id", "child_id", studios.Depth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -486,6 +487,32 @@ func (qb *performerFilterHandler) studiosCriterionHandler(studios *models.Hierar
|
|||||||
f.addLeftJoin(derivedPerformerStudioTable, "", fmt.Sprintf("performers.id = %s.performer_id", derivedPerformerStudioTable))
|
f.addLeftJoin(derivedPerformerStudioTable, "", fmt.Sprintf("performers.id = %s.performer_id", derivedPerformerStudioTable))
|
||||||
f.addWhere(fmt.Sprintf("%s.performer_id IS %s NULL", derivedPerformerStudioTable, clauseCondition))
|
f.addWhere(fmt.Sprintf("%s.performer_id IS %s NULL", derivedPerformerStudioTable, clauseCondition))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #6412 - handle excludes as well
|
||||||
|
if len(studios.Excludes) > 0 {
|
||||||
|
excludeValuesClause, err := getHierarchicalValues(ctx, studios.Excludes, studioTable, "", "parent_id", "child_id", studios.Depth)
|
||||||
|
if err != nil {
|
||||||
|
f.setError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.addWith("exclude_studio(root_id, item_id) AS (" + excludeValuesClause + ")")
|
||||||
|
|
||||||
|
excludeTemplStr := `SELECT performer_id FROM {primaryTable}
|
||||||
|
INNER JOIN {joinTable} ON {primaryTable}.id = {joinTable}.{primaryFK}
|
||||||
|
INNER JOIN exclude_studio ON {primaryTable}.studio_id = exclude_studio.item_id`
|
||||||
|
|
||||||
|
var unions []string
|
||||||
|
for _, c := range formatMaps {
|
||||||
|
unions = append(unions, utils.StrFormat(excludeTemplStr, c))
|
||||||
|
}
|
||||||
|
|
||||||
|
const excludePerformerStudioTable = "performer_studio_exclude"
|
||||||
|
f.addWith(fmt.Sprintf("%s AS (%s)", excludePerformerStudioTable, strings.Join(unions, " UNION ")))
|
||||||
|
|
||||||
|
f.addLeftJoin(excludePerformerStudioTable, "", fmt.Sprintf("performers.id = %s.performer_id", excludePerformerStudioTable))
|
||||||
|
f.addWhere(fmt.Sprintf("%s.performer_id IS NULL", excludePerformerStudioTable))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1160,6 +1160,98 @@ func TestPerformerQuery(t *testing.T) {
|
|||||||
[]int{performerIdx1WithScene, performerIdxWithScene},
|
[]int{performerIdx1WithScene, performerIdxWithScene},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"include scene studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdxWithScenePerformer])},
|
||||||
|
Modifier: models.CriterionModifierIncludes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]int{performerIdxWithSceneStudio},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include image studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdxWithImagePerformer])},
|
||||||
|
Modifier: models.CriterionModifierIncludes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]int{performerIdxWithImageStudio},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include gallery studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdxWithGalleryPerformer])},
|
||||||
|
Modifier: models.CriterionModifierIncludes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]int{performerIdxWithGalleryStudio},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exclude scene studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdxWithScenePerformer])},
|
||||||
|
Modifier: models.CriterionModifierExcludes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
[]int{performerIdxWithSceneStudio},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exclude image studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdxWithImagePerformer])},
|
||||||
|
Modifier: models.CriterionModifierExcludes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
[]int{performerIdxWithImageStudio},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exclude gallery studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdxWithGalleryPerformer])},
|
||||||
|
Modifier: models.CriterionModifierExcludes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
[]int{performerIdxWithGalleryStudio},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include and exclude scene studio",
|
||||||
|
nil,
|
||||||
|
&models.PerformerFilterType{
|
||||||
|
Studios: &models.HierarchicalMultiCriterionInput{
|
||||||
|
Value: []string{strconv.Itoa(studioIDs[studioIdx1WithTwoScenePerformer])},
|
||||||
|
Modifier: models.CriterionModifierIncludes,
|
||||||
|
Excludes: []string{strconv.Itoa(studioIDs[studioIdx2WithTwoScenePerformer])},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
[]int{performerIdxWithTwoSceneStudio},
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -2260,7 +2352,7 @@ func TestPerformerQuerySortScenesCount(t *testing.T) {
|
|||||||
assert.True(t, len(performers) > 0)
|
assert.True(t, len(performers) > 0)
|
||||||
lastPerformer := performers[len(performers)-1]
|
lastPerformer := performers[len(performers)-1]
|
||||||
|
|
||||||
assert.Equal(t, performerIDs[performerIdxWithTag], lastPerformer.ID)
|
assert.Equal(t, performerIDs[performerIdxWithTwoSceneStudio], lastPerformer.ID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ const (
|
|||||||
sceneIdxWithPerformerTwoTags
|
sceneIdxWithPerformerTwoTags
|
||||||
sceneIdxWithSpacedName
|
sceneIdxWithSpacedName
|
||||||
sceneIdxWithStudioPerformer
|
sceneIdxWithStudioPerformer
|
||||||
|
sceneIdx1WithTwoStudioPerformer
|
||||||
|
sceneIdx2WithTwoStudioPerformer
|
||||||
sceneIdxWithGrandChildStudio
|
sceneIdxWithGrandChildStudio
|
||||||
sceneIdxMissingPhash
|
sceneIdxMissingPhash
|
||||||
sceneIdxWithPerformerParentTag
|
sceneIdxWithPerformerParentTag
|
||||||
@@ -138,6 +140,7 @@ const (
|
|||||||
performerIdxWithSceneStudio
|
performerIdxWithSceneStudio
|
||||||
performerIdxWithImageStudio
|
performerIdxWithImageStudio
|
||||||
performerIdxWithGalleryStudio
|
performerIdxWithGalleryStudio
|
||||||
|
performerIdxWithTwoSceneStudio
|
||||||
performerIdxWithParentTag
|
performerIdxWithParentTag
|
||||||
// new indexes above
|
// new indexes above
|
||||||
// performers with dup names start from the end
|
// performers with dup names start from the end
|
||||||
@@ -257,6 +260,8 @@ const (
|
|||||||
studioIdxWithScenePerformer
|
studioIdxWithScenePerformer
|
||||||
studioIdxWithImagePerformer
|
studioIdxWithImagePerformer
|
||||||
studioIdxWithGalleryPerformer
|
studioIdxWithGalleryPerformer
|
||||||
|
studioIdx1WithTwoScenePerformer
|
||||||
|
studioIdx2WithTwoScenePerformer
|
||||||
studioIdxWithTag
|
studioIdxWithTag
|
||||||
studioIdx2WithTag
|
studioIdx2WithTag
|
||||||
studioIdxWithTwoTags
|
studioIdxWithTwoTags
|
||||||
@@ -393,6 +398,8 @@ var (
|
|||||||
sceneIdx1WithPerformer: {performerIdxWithTwoScenes},
|
sceneIdx1WithPerformer: {performerIdxWithTwoScenes},
|
||||||
sceneIdx2WithPerformer: {performerIdxWithTwoScenes},
|
sceneIdx2WithPerformer: {performerIdxWithTwoScenes},
|
||||||
sceneIdxWithStudioPerformer: {performerIdxWithSceneStudio},
|
sceneIdxWithStudioPerformer: {performerIdxWithSceneStudio},
|
||||||
|
sceneIdx1WithTwoStudioPerformer: {performerIdxWithTwoSceneStudio},
|
||||||
|
sceneIdx2WithTwoStudioPerformer: {performerIdxWithTwoSceneStudio},
|
||||||
sceneIdxWithPerformerParentTag: {performerIdxWithParentTag},
|
sceneIdxWithPerformerParentTag: {performerIdxWithParentTag},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,6 +417,8 @@ var (
|
|||||||
sceneIdx1WithStudio: studioIdxWithTwoScenes,
|
sceneIdx1WithStudio: studioIdxWithTwoScenes,
|
||||||
sceneIdx2WithStudio: studioIdxWithTwoScenes,
|
sceneIdx2WithStudio: studioIdxWithTwoScenes,
|
||||||
sceneIdxWithStudioPerformer: studioIdxWithScenePerformer,
|
sceneIdxWithStudioPerformer: studioIdxWithScenePerformer,
|
||||||
|
sceneIdx1WithTwoStudioPerformer: studioIdx1WithTwoScenePerformer,
|
||||||
|
sceneIdx2WithTwoStudioPerformer: studioIdx2WithTwoScenePerformer,
|
||||||
sceneIdxWithGrandChildStudio: studioIdxWithGrandParent,
|
sceneIdxWithGrandChildStudio: studioIdxWithGrandParent,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user