mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +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:
@@ -1945,154 +1945,369 @@ func TestGalleryQueryIsMissingDate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGalleryQueryPerformers(t *testing.T) {
|
||||
withTxn(func(ctx context.Context) error {
|
||||
sqb := db.Gallery
|
||||
performerCriterion := models.MultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(performerIDs[performerIdxWithGallery]),
|
||||
strconv.Itoa(performerIDs[performerIdx1WithGallery]),
|
||||
tests := []struct {
|
||||
name string
|
||||
filter models.MultiCriterionInput
|
||||
includeIdxs []int
|
||||
excludeIdxs []int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"includes",
|
||||
models.MultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(performerIDs[performerIdxWithGallery]),
|
||||
strconv.Itoa(performerIDs[performerIdx1WithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
}
|
||||
|
||||
galleryFilter := models.GalleryFilterType{
|
||||
Performers: &performerCriterion,
|
||||
}
|
||||
|
||||
galleries := queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
|
||||
assert.Len(t, galleries, 2)
|
||||
|
||||
// ensure ids are correct
|
||||
for _, gallery := range galleries {
|
||||
assert.True(t, gallery.ID == galleryIDs[galleryIdxWithPerformer] || gallery.ID == galleryIDs[galleryIdxWithTwoPerformers])
|
||||
}
|
||||
|
||||
performerCriterion = models.MultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(performerIDs[performerIdx1WithGallery]),
|
||||
strconv.Itoa(performerIDs[performerIdx2WithGallery]),
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
galleryIdxWithTwoPerformers,
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
}
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
|
||||
assert.Len(t, galleries, 1)
|
||||
assert.Equal(t, galleryIDs[galleryIdxWithTwoPerformers], galleries[0].ID)
|
||||
|
||||
performerCriterion = models.MultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(performerIDs[performerIdx1WithGallery]),
|
||||
[]int{
|
||||
galleryIdxWithImage,
|
||||
},
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
}
|
||||
false,
|
||||
},
|
||||
{
|
||||
"includes all",
|
||||
models.MultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(performerIDs[performerIdx1WithGallery]),
|
||||
strconv.Itoa(performerIDs[performerIdx2WithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithTwoPerformers,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"excludes",
|
||||
models.MultiCriterionInput{
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
Value: []string{strconv.Itoa(tagIDs[performerIdx1WithGallery])},
|
||||
},
|
||||
nil,
|
||||
[]int{galleryIdxWithTwoPerformers},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"is null",
|
||||
models.MultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIsNull,
|
||||
},
|
||||
[]int{galleryIdxWithTag},
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
galleryIdxWithTwoPerformers,
|
||||
galleryIdxWithPerformerTwoTags,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not null",
|
||||
models.MultiCriterionInput{
|
||||
Modifier: models.CriterionModifierNotNull,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
galleryIdxWithTwoPerformers,
|
||||
galleryIdxWithPerformerTwoTags,
|
||||
},
|
||||
[]int{galleryIdxWithTag},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"equals",
|
||||
models.MultiCriterionInput{
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[performerIdx1WithGallery]),
|
||||
strconv.Itoa(tagIDs[performerIdx2WithGallery]),
|
||||
},
|
||||
},
|
||||
[]int{galleryIdxWithTwoPerformers},
|
||||
[]int{
|
||||
galleryIdxWithThreePerformers,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not equals",
|
||||
models.MultiCriterionInput{
|
||||
Modifier: models.CriterionModifierNotEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[performerIdx1WithGallery]),
|
||||
strconv.Itoa(tagIDs[performerIdx2WithGallery]),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
q := getGalleryStringValue(galleryIdxWithTwoPerformers, titleField)
|
||||
findFilter := models.FindFilterType{
|
||||
Q: &q,
|
||||
}
|
||||
for _, tt := range tests {
|
||||
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
|
||||
assert := assert.New(t)
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 0)
|
||||
results, _, err := db.Gallery.Query(ctx, &models.GalleryFilterType{
|
||||
Performers: &tt.filter,
|
||||
}, nil)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GalleryStore.Query() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
ids := galleriesToIDs(results)
|
||||
|
||||
include := indexesToIDs(galleryIDs, tt.includeIdxs)
|
||||
exclude := indexesToIDs(galleryIDs, tt.excludeIdxs)
|
||||
|
||||
for _, i := range include {
|
||||
assert.Contains(ids, i)
|
||||
}
|
||||
for _, e := range exclude {
|
||||
assert.NotContains(ids, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGalleryQueryTags(t *testing.T) {
|
||||
withTxn(func(ctx context.Context) error {
|
||||
sqb := db.Gallery
|
||||
tagCriterion := models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdxWithGallery]),
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
tests := []struct {
|
||||
name string
|
||||
filter models.HierarchicalMultiCriterionInput
|
||||
includeIdxs []int
|
||||
excludeIdxs []int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"includes",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdxWithGallery]),
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
}
|
||||
|
||||
galleryFilter := models.GalleryFilterType{
|
||||
Tags: &tagCriterion,
|
||||
}
|
||||
|
||||
galleries := queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
assert.Len(t, galleries, 2)
|
||||
|
||||
// ensure ids are correct
|
||||
for _, gallery := range galleries {
|
||||
assert.True(t, gallery.ID == galleryIDs[galleryIdxWithTag] || gallery.ID == galleryIDs[galleryIdxWithTwoTags])
|
||||
}
|
||||
|
||||
tagCriterion = models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
strconv.Itoa(tagIDs[tagIdx2WithGallery]),
|
||||
[]int{
|
||||
galleryIdxWithTag,
|
||||
galleryIdxWithTwoTags,
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
}
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
|
||||
assert.Len(t, galleries, 1)
|
||||
assert.Equal(t, galleryIDs[galleryIdxWithTwoTags], galleries[0].ID)
|
||||
|
||||
tagCriterion = models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
[]int{
|
||||
galleryIdxWithImage,
|
||||
},
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
}
|
||||
false,
|
||||
},
|
||||
{
|
||||
"includes all",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
strconv.Itoa(tagIDs[tagIdx2WithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithTwoTags,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithTag,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"excludes",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
Value: []string{strconv.Itoa(tagIDs[tagIdx1WithGallery])},
|
||||
},
|
||||
nil,
|
||||
[]int{galleryIdxWithTwoTags},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"is null",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIsNull,
|
||||
},
|
||||
[]int{galleryIdx1WithPerformer},
|
||||
[]int{
|
||||
galleryIdxWithTag,
|
||||
galleryIdxWithTwoTags,
|
||||
galleryIdxWithThreeTags,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not null",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierNotNull,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithTag,
|
||||
galleryIdxWithTwoTags,
|
||||
galleryIdxWithThreeTags,
|
||||
},
|
||||
[]int{galleryIdx1WithPerformer},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"equals",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
strconv.Itoa(tagIDs[tagIdx2WithGallery]),
|
||||
},
|
||||
},
|
||||
[]int{galleryIdxWithTwoTags},
|
||||
[]int{
|
||||
galleryIdxWithThreeTags,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not equals",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierNotEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithGallery]),
|
||||
strconv.Itoa(tagIDs[tagIdx2WithGallery]),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
q := getGalleryStringValue(galleryIdxWithTwoTags, titleField)
|
||||
findFilter := models.FindFilterType{
|
||||
Q: &q,
|
||||
}
|
||||
for _, tt := range tests {
|
||||
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
|
||||
assert := assert.New(t)
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 0)
|
||||
results, _, err := db.Gallery.Query(ctx, &models.GalleryFilterType{
|
||||
Tags: &tt.filter,
|
||||
}, nil)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GalleryStore.Query() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
ids := galleriesToIDs(results)
|
||||
|
||||
include := indexesToIDs(imageIDs, tt.includeIdxs)
|
||||
exclude := indexesToIDs(imageIDs, tt.excludeIdxs)
|
||||
|
||||
for _, i := range include {
|
||||
assert.Contains(ids, i)
|
||||
}
|
||||
for _, e := range exclude {
|
||||
assert.NotContains(ids, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGalleryQueryStudio(t *testing.T) {
|
||||
withTxn(func(ctx context.Context) error {
|
||||
sqb := db.Gallery
|
||||
studioCriterion := models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
tests := []struct {
|
||||
name string
|
||||
q string
|
||||
studioCriterion models.HierarchicalMultiCriterionInput
|
||||
expectedIDs []int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"includes",
|
||||
"",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
}
|
||||
|
||||
galleryFilter := models.GalleryFilterType{
|
||||
Studios: &studioCriterion,
|
||||
}
|
||||
|
||||
galleries := queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
|
||||
assert.Len(t, galleries, 1)
|
||||
|
||||
// ensure id is correct
|
||||
assert.Equal(t, galleryIDs[galleryIdxWithStudio], galleries[0].ID)
|
||||
|
||||
studioCriterion = models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
[]int{galleryIDs[galleryIdxWithStudio]},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"excludes",
|
||||
getGalleryStringValue(galleryIdxWithStudio, titleField),
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
},
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
}
|
||||
[]int{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"excludes includes null",
|
||||
getGalleryStringValue(galleryIdxWithImage, titleField),
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
},
|
||||
[]int{galleryIDs[galleryIdxWithImage]},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"equals",
|
||||
"",
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
},
|
||||
[]int{galleryIDs[galleryIdxWithStudio]},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not equals",
|
||||
getGalleryStringValue(galleryIdxWithStudio, titleField),
|
||||
models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(studioIDs[studioIdxWithGallery]),
|
||||
},
|
||||
Modifier: models.CriterionModifierNotEquals,
|
||||
},
|
||||
[]int{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
q := getGalleryStringValue(galleryIdxWithStudio, titleField)
|
||||
findFilter := models.FindFilterType{
|
||||
Q: &q,
|
||||
}
|
||||
qb := db.Gallery
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 0)
|
||||
for _, tt := range tests {
|
||||
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
|
||||
studioCriterion := tt.studioCriterion
|
||||
|
||||
return nil
|
||||
})
|
||||
galleryFilter := models.GalleryFilterType{
|
||||
Studios: &studioCriterion,
|
||||
}
|
||||
|
||||
var findFilter *models.FindFilterType
|
||||
if tt.q != "" {
|
||||
findFilter = &models.FindFilterType{
|
||||
Q: &tt.q,
|
||||
}
|
||||
}
|
||||
|
||||
gallerys := queryGallery(ctx, t, qb, &galleryFilter, findFilter)
|
||||
|
||||
assert.ElementsMatch(t, galleriesToIDs(gallerys), tt.expectedIDs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGalleryQueryStudioDepth(t *testing.T) {
|
||||
@@ -2157,81 +2372,198 @@ func TestGalleryQueryStudioDepth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGalleryQueryPerformerTags(t *testing.T) {
|
||||
withTxn(func(ctx context.Context) error {
|
||||
sqb := db.Gallery
|
||||
tagCriterion := models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdxWithPerformer]),
|
||||
strconv.Itoa(tagIDs[tagIdx1WithPerformer]),
|
||||
allDepth := -1
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
findFilter *models.FindFilterType
|
||||
filter *models.GalleryFilterType
|
||||
includeIdxs []int
|
||||
excludeIdxs []int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"includes",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdxWithPerformer]),
|
||||
strconv.Itoa(tagIDs[tagIdx1WithPerformer]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
},
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
}
|
||||
|
||||
galleryFilter := models.GalleryFilterType{
|
||||
PerformerTags: &tagCriterion,
|
||||
}
|
||||
|
||||
galleries := queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
assert.Len(t, galleries, 2)
|
||||
|
||||
// ensure ids are correct
|
||||
for _, gallery := range galleries {
|
||||
assert.True(t, gallery.ID == galleryIDs[galleryIdxWithPerformerTag] || gallery.ID == galleryIDs[galleryIdxWithPerformerTwoTags])
|
||||
}
|
||||
|
||||
tagCriterion = models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithPerformer]),
|
||||
strconv.Itoa(tagIDs[tagIdx2WithPerformer]),
|
||||
[]int{
|
||||
galleryIdxWithPerformerTag,
|
||||
galleryIdxWithPerformerTwoTags,
|
||||
galleryIdxWithTwoPerformerTag,
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
}
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, nil)
|
||||
|
||||
assert.Len(t, galleries, 1)
|
||||
assert.Equal(t, galleryIDs[galleryIdxWithPerformerTwoTags], galleries[0].ID)
|
||||
|
||||
tagCriterion = models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithPerformer]),
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
},
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
}
|
||||
false,
|
||||
},
|
||||
{
|
||||
"includes sub-tags",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdxWithParentAndChild]),
|
||||
},
|
||||
Depth: &allDepth,
|
||||
Modifier: models.CriterionModifierIncludes,
|
||||
},
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformerParentTag,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
galleryIdxWithPerformerTag,
|
||||
galleryIdxWithPerformerTwoTags,
|
||||
galleryIdxWithTwoPerformerTag,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"includes all",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx1WithPerformer]),
|
||||
strconv.Itoa(tagIDs[tagIdx2WithPerformer]),
|
||||
},
|
||||
Modifier: models.CriterionModifierIncludesAll,
|
||||
},
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformerTwoTags,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
galleryIdxWithPerformerTag,
|
||||
galleryIdxWithTwoPerformerTag,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"excludes performer tag tagIdx2WithPerformer",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
Value: []string{strconv.Itoa(tagIDs[tagIdx2WithPerformer])},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
[]int{galleryIdxWithTwoPerformerTag},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"excludes sub-tags",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdxWithParentAndChild]),
|
||||
},
|
||||
Depth: &allDepth,
|
||||
Modifier: models.CriterionModifierExcludes,
|
||||
},
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformer,
|
||||
galleryIdxWithPerformerTag,
|
||||
galleryIdxWithPerformerTwoTags,
|
||||
galleryIdxWithTwoPerformerTag,
|
||||
},
|
||||
[]int{
|
||||
galleryIdxWithPerformerParentTag,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"is null",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIsNull,
|
||||
},
|
||||
},
|
||||
[]int{galleryIdx1WithImage},
|
||||
[]int{galleryIdxWithPerformerTag},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not null",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierNotNull,
|
||||
},
|
||||
},
|
||||
[]int{galleryIdxWithPerformerTag},
|
||||
[]int{galleryIdx1WithImage},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"equals",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx2WithPerformer]),
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"not equals",
|
||||
nil,
|
||||
&models.GalleryFilterType{
|
||||
PerformerTags: &models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierNotEquals,
|
||||
Value: []string{
|
||||
strconv.Itoa(tagIDs[tagIdx2WithPerformer]),
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
q := getGalleryStringValue(galleryIdxWithPerformerTwoTags, titleField)
|
||||
findFilter := models.FindFilterType{
|
||||
Q: &q,
|
||||
}
|
||||
for _, tt := range tests {
|
||||
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
|
||||
assert := assert.New(t)
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 0)
|
||||
results, _, err := db.Gallery.Query(ctx, tt.filter, tt.findFilter)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ImageStore.Query() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
tagCriterion = models.HierarchicalMultiCriterionInput{
|
||||
Modifier: models.CriterionModifierIsNull,
|
||||
}
|
||||
q = getGalleryStringValue(galleryIdx1WithImage, titleField)
|
||||
ids := galleriesToIDs(results)
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 1)
|
||||
assert.Equal(t, galleryIDs[galleryIdx1WithImage], galleries[0].ID)
|
||||
include := indexesToIDs(galleryIDs, tt.includeIdxs)
|
||||
exclude := indexesToIDs(galleryIDs, tt.excludeIdxs)
|
||||
|
||||
q = getGalleryStringValue(galleryIdxWithPerformerTag, titleField)
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 0)
|
||||
|
||||
tagCriterion.Modifier = models.CriterionModifierNotNull
|
||||
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 1)
|
||||
assert.Equal(t, galleryIDs[galleryIdxWithPerformerTag], galleries[0].ID)
|
||||
|
||||
q = getGalleryStringValue(galleryIdx1WithImage, titleField)
|
||||
galleries = queryGallery(ctx, t, sqb, &galleryFilter, &findFilter)
|
||||
assert.Len(t, galleries, 0)
|
||||
|
||||
return nil
|
||||
})
|
||||
for _, i := range include {
|
||||
assert.Contains(ids, i)
|
||||
}
|
||||
for _, e := range exclude {
|
||||
assert.NotContains(ids, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGalleryQueryTagCount(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user