mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
Fix joined hierarchical filtering (#3775)
* Fix joined hierarchical filtering * Fix scene performer tag filter * Generalise performer tag handler * Add unit tests * Add equals handling * Make performer tags equals/not equals unsupported * Make tags not equals unsupported * Make not equals unsupported for performers criterion * Support equals/not equals for studio criterion * Fix marker scene tags equals filter * Fix scene performer tag filter * Make equals/not equals unsupported for hierarchical criterion * Use existing studio handler in movie * Hide unsupported tag modifier options * Use existing performer tags logic where possible * Restore old parent/child filter logic * Disable sub-tags in equals modifier for tags criterion
This commit is contained in:
@@ -5,9 +5,12 @@ package sqlite_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
||||
"github.com/stashapp/stash/pkg/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -50,7 +53,7 @@ func TestMarkerCountByTagID(t *testing.T) {
|
||||
t.Errorf("error calling CountByTagID: %s", err.Error())
|
||||
}
|
||||
|
||||
assert.Equal(t, 3, markerCount)
|
||||
assert.Equal(t, 4, markerCount)
|
||||
|
||||
markerCount, err = mqb.CountByTagID(ctx, tagIDs[tagIdxWithMarkers])
|
||||
|
||||
@@ -151,7 +154,7 @@ func TestMarkerQuerySceneTags(t *testing.T) {
|
||||
}
|
||||
|
||||
withTxn(func(ctx context.Context) error {
|
||||
testTags := func(m *models.SceneMarker, markerFilter *models.SceneMarkerFilterType) {
|
||||
testTags := func(t *testing.T, m *models.SceneMarker, markerFilter *models.SceneMarkerFilterType) {
|
||||
s, err := db.Scene.Find(ctx, int(m.SceneID.Int64))
|
||||
if err != nil {
|
||||
t.Errorf("error getting marker tag ids: %v", err)
|
||||
@@ -164,11 +167,40 @@ func TestMarkerQuerySceneTags(t *testing.T) {
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
if markerFilter.SceneTags.Modifier == models.CriterionModifierNotNull && len(tagIDs) == 0 {
|
||||
t.Errorf("expected marker %d to have scene tags - found 0", m.ID)
|
||||
values, _ := stringslice.StringSliceToIntSlice(markerFilter.SceneTags.Value)
|
||||
switch markerFilter.SceneTags.Modifier {
|
||||
case models.CriterionModifierIsNull:
|
||||
if len(tagIDs) > 0 {
|
||||
t.Errorf("expected marker %d to have no scene tags - found %d", m.ID, len(tagIDs))
|
||||
}
|
||||
case models.CriterionModifierNotNull:
|
||||
if len(tagIDs) == 0 {
|
||||
t.Errorf("expected marker %d to have scene tags - found 0", m.ID)
|
||||
}
|
||||
case models.CriterionModifierIncludes:
|
||||
for _, v := range values {
|
||||
assert.Contains(t, tagIDs, v)
|
||||
}
|
||||
case models.CriterionModifierExcludes:
|
||||
for _, v := range values {
|
||||
assert.NotContains(t, tagIDs, v)
|
||||
}
|
||||
case models.CriterionModifierEquals:
|
||||
for _, v := range values {
|
||||
assert.Contains(t, tagIDs, v)
|
||||
}
|
||||
assert.Len(t, tagIDs, len(values))
|
||||
case models.CriterionModifierNotEquals:
|
||||
foundAll := true
|
||||
for _, v := range values {
|
||||
if !intslice.IntInclude(tagIDs, v) {
|
||||
foundAll = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if foundAll && len(tagIDs) == len(values) {
|
||||
t.Errorf("expected marker %d to have scene tags not equal to %v - found %v", m.ID, values, tagIDs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +223,70 @@ func TestMarkerQuerySceneTags(t *testing.T) {
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"includes",
|
||||
&models.SceneMarkerFilterType{
|
||||
SceneTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx3WithScene]),
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"includes all",
|
||||
&models.SceneMarkerFilterType{
|
||||
SceneTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx2WithScene]),
|
||||
strconv.Itoa(tagIDs[tagIdx3WithScene]),
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"equals",
|
||||
&models.SceneMarkerFilterType{
|
||||
SceneTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx2WithScene]),
|
||||
strconv.Itoa(tagIDs[tagIdx3WithScene]),
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
// not equals not supported
|
||||
// {
|
||||
// "not equals",
|
||||
// &models.SceneMarkerFilterType{
|
||||
// SceneTags: &models.HierarchicalMultiCriterionInput{
|
||||
// Modifier: models.CriterionModifierNotEquals,
|
||||
// Value: []string{
|
||||
// strconv.Itoa(tagIDs[tagIdx2WithScene]),
|
||||
// strconv.Itoa(tagIDs[tagIdx3WithScene]),
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// nil,
|
||||
// },
|
||||
{
|
||||
"excludes",
|
||||
&models.SceneMarkerFilterType{
|
||||
SceneTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx2WithScene]),
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
@@ -198,7 +294,7 @@ func TestMarkerQuerySceneTags(t *testing.T) {
|
||||
markers := queryMarkers(ctx, t, sqlite.SceneMarkerReaderWriter, tc.markerFilter, tc.findFilter)
|
||||
assert.Greater(t, len(markers), 0)
|
||||
for _, m := range markers {
|
||||
testTags(m, tc.markerFilter)
|
||||
testTags(t, m, tc.markerFilter)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user