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:
WithoutPants
2023-06-06 13:01:50 +10:00
committed by GitHub
parent 4acf843229
commit 256e0a11ea
19 changed files with 2153 additions and 938 deletions

View File

@@ -669,7 +669,7 @@ func (qb *ImageStore) makeFilter(ctx context.Context, imageFilter *models.ImageF
query.handleCriterion(ctx, imageGalleriesCriterionHandler(qb, imageFilter.Galleries))
query.handleCriterion(ctx, imagePerformersCriterionHandler(qb, imageFilter.Performers))
query.handleCriterion(ctx, imagePerformerCountCriterionHandler(qb, imageFilter.PerformerCount))
query.handleCriterion(ctx, imageStudioCriterionHandler(qb, imageFilter.Studios))
query.handleCriterion(ctx, studioCriterionHandler(imageTable, imageFilter.Studios))
query.handleCriterion(ctx, imagePerformerTagsCriterionHandler(qb, imageFilter.PerformerTags))
query.handleCriterion(ctx, imagePerformerFavoriteCriterionHandler(imageFilter.PerformerFavorite))
query.handleCriterion(ctx, timestampCriterionHandler(imageFilter.CreatedAt, "images.created_at"))
@@ -946,51 +946,12 @@ GROUP BY performers_images.image_id HAVING SUM(performers.favorite) = 0)`, "nofa
}
}
func imageStudioCriterionHandler(qb *ImageStore, studios *models.HierarchicalMultiCriterionInput) criterionHandlerFunc {
h := hierarchicalMultiCriterionHandlerBuilder{
tx: qb.tx,
primaryTable: imageTable,
foreignTable: studioTable,
foreignFK: studioIDColumn,
parentFK: "parent_id",
}
return h.handler(studios)
}
func imagePerformerTagsCriterionHandler(qb *ImageStore, tags *models.HierarchicalMultiCriterionInput) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if tags != nil {
if tags.Modifier == models.CriterionModifierIsNull || tags.Modifier == models.CriterionModifierNotNull {
var notClause string
if tags.Modifier == models.CriterionModifierNotNull {
notClause = "NOT"
}
f.addLeftJoin("performers_images", "", "images.id = performers_images.image_id")
f.addLeftJoin("performers_tags", "", "performers_images.performer_id = performers_tags.performer_id")
f.addWhere(fmt.Sprintf("performers_tags.tag_id IS %s NULL", notClause))
return
}
if len(tags.Value) == 0 {
return
}
valuesClause := getHierarchicalValues(ctx, qb.tx, tags.Value, tagTable, "tags_relations", "", tags.Depth)
f.addWith(`performer_tags AS (
SELECT pi.image_id, t.column1 AS root_tag_id FROM performers_images pi
INNER JOIN performers_tags pt ON pt.performer_id = pi.performer_id
INNER JOIN (` + valuesClause + `) t ON t.column2 = pt.tag_id
)`)
f.addLeftJoin("performer_tags", "", "performer_tags.image_id = images.id")
addHierarchicalConditionClauses(f, *tags, "performer_tags", "root_tag_id")
}
func imagePerformerTagsCriterionHandler(qb *ImageStore, tags *models.HierarchicalMultiCriterionInput) criterionHandler {
return &joinedPerformerTagsHandler{
criterion: tags,
primaryTable: imageTable,
joinTable: performersImagesTable,
joinPrimaryKey: imageIDColumn,
}
}