Skip to content

Commit

Permalink
Add (not) between modifiers for number criterion
Browse files Browse the repository at this point in the history
  • Loading branch information
gitgiggety committed Jul 6, 2021
1 parent 73f99f0 commit f0fe2cc
Show file tree
Hide file tree
Showing 18 changed files with 481 additions and 239 deletions.
8 changes: 7 additions & 1 deletion graphql/schema/types/filters.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@ enum CriterionModifier {
MATCHES_REGEX,
"""NOT MATCHES REGEX"""
NOT_MATCHES_REGEX,
"""> AND <"""
BETWEEN,
"""<= OR >="""
NOT_BETWEEN,
}

input StringCriterionInput {
Expand All @@ -330,7 +334,9 @@ input StringCriterionInput {
}

input IntCriterionInput {
value: Int!
exact: Int!
lower: Int!
upper: Int!
modifier: CriterionModifier!
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/dlna/cds.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ func (me *contentDirectoryService) getRatingScenes(paths []string, host string)
sceneFilter := &models.SceneFilterType{
Rating: &models.IntCriterionInput{
Modifier: models.CriterionModifierEquals,
Value: r,
Exact: r,
},
}

Expand Down
17 changes: 4 additions & 13 deletions pkg/sqlite/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,8 @@ func stringCriterionHandler(c *models.StringCriterionInput, column string) crite
func intCriterionHandler(c *models.IntCriterionInput, column string) criterionHandlerFunc {
return func(f *filterBuilder) {
if c != nil {
clause, count := getIntCriterionWhereClause(column, *c)

if count == 1 {
f.addWhere(clause, c.Value)
} else {
f.addWhere(clause)
}
clause, args := getIntCriterionWhereClause(column, *c)
f.addWhere(clause, args...)
}
}
}
Expand Down Expand Up @@ -495,13 +490,9 @@ type countCriterionHandlerBuilder struct {
func (m *countCriterionHandlerBuilder) handler(criterion *models.IntCriterionInput) criterionHandlerFunc {
return func(f *filterBuilder) {
if criterion != nil {
clause, count := getCountCriterionClause(m.primaryTable, m.joinTable, m.primaryFK, *criterion)
clause, args := getCountCriterionClause(m.primaryTable, m.joinTable, m.primaryFK, *criterion)

if count == 1 {
f.addWhere(clause, criterion.Value)
} else {
f.addWhere(clause)
}
f.addWhere(clause, args...)
}
}
}
Expand Down
24 changes: 18 additions & 6 deletions pkg/sqlite/gallery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,9 @@ func TestGalleryQueryPathAndRating(t *testing.T) {
},
And: &models.GalleryFilterType{
Rating: &models.IntCriterionInput{
Value: int(galleryRating.Int64),
Exact: int(galleryRating.Int64),
Upper: int(galleryRating.Int64),
Lower: int(galleryRating.Int64),
Modifier: models.CriterionModifierEquals,
},
},
Expand Down Expand Up @@ -268,7 +270,9 @@ func TestGalleryQueryPathNotRating(t *testing.T) {
}

ratingCriterion := models.IntCriterionInput{
Value: int(galleryRating.Int64),
Exact: int(galleryRating.Int64),
Upper: int(galleryRating.Int64),
Lower: int(galleryRating.Int64),
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -389,7 +393,9 @@ func verifyGalleryQuery(t *testing.T, filter models.GalleryFilterType, verifyFn
func TestGalleryQueryRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Exact: rating,
Upper: rating,
Lower: rating,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -830,7 +836,9 @@ func TestGalleryQueryPerformerTags(t *testing.T) {
func TestGalleryQueryTagCount(t *testing.T) {
const tagCount = 1
tagCountCriterion := models.IntCriterionInput{
Value: tagCount,
Exact: tagCount,
Upper: tagCount,
Lower: tagCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -871,7 +879,9 @@ func verifyGalleriesTagCount(t *testing.T, tagCountCriterion models.IntCriterion
func TestGalleryQueryPerformerCount(t *testing.T) {
const performerCount = 1
performerCountCriterion := models.IntCriterionInput{
Value: performerCount,
Exact: performerCount,
Upper: performerCount,
Lower: performerCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -928,7 +938,9 @@ func TestGalleryQueryAverageResolution(t *testing.T) {
func TestGalleryQueryImageCount(t *testing.T) {
const imageCount = 0
imageCountCriterion := models.IntCriterionInput{
Value: imageCount,
Exact: imageCount,
Upper: imageCount,
Lower: imageCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down
24 changes: 18 additions & 6 deletions pkg/sqlite/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,9 @@ func TestImageQueryPathAndRating(t *testing.T) {
},
And: &models.ImageFilterType{
Rating: &models.IntCriterionInput{
Value: int(imageRating.Int64),
Exact: int(imageRating.Int64),
Upper: int(imageRating.Int64),
Lower: int(imageRating.Int64),
Modifier: models.CriterionModifierEquals,
},
},
Expand Down Expand Up @@ -230,7 +232,9 @@ func TestImageQueryPathNotRating(t *testing.T) {
}

ratingCriterion := models.IntCriterionInput{
Value: int(imageRating.Int64),
Exact: int(imageRating.Int64),
Upper: int(imageRating.Int64),
Lower: int(imageRating.Int64),
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -295,7 +299,9 @@ func TestImageIllegalQuery(t *testing.T) {
func TestImageQueryRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Exact: rating,
Upper: rating,
Lower: rating,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -340,7 +346,9 @@ func verifyImagesRating(t *testing.T, ratingCriterion models.IntCriterionInput)
func TestImageQueryOCounter(t *testing.T) {
const oCounter = 1
oCounterCriterion := models.IntCriterionInput{
Value: oCounter,
Exact: oCounter,
Upper: oCounter,
Lower: oCounter,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -953,7 +961,9 @@ func TestImageQueryPerformerTags(t *testing.T) {
func TestImageQueryTagCount(t *testing.T) {
const tagCount = 1
tagCountCriterion := models.IntCriterionInput{
Value: tagCount,
Exact: tagCount,
Upper: tagCount,
Lower: tagCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -994,7 +1004,9 @@ func verifyImagesTagCount(t *testing.T, tagCountCriterion models.IntCriterionInp
func TestImageQueryPerformerCount(t *testing.T) {
const performerCount = 1
performerCountCriterion := models.IntCriterionInput{
Value: performerCount,
Exact: performerCount,
Upper: performerCount,
Lower: performerCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down
43 changes: 7 additions & 36 deletions pkg/sqlite/performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package sqlite
import (
"database/sql"
"fmt"
"strconv"
"strings"

"github.com/stashapp/stash/pkg/models"
Expand Down Expand Up @@ -356,48 +355,20 @@ func performerIsMissingCriterionHandler(qb *performerQueryBuilder, isMissing *st
func yearFilterCriterionHandler(year *models.IntCriterionInput, col string) criterionHandlerFunc {
return func(f *filterBuilder) {
if year != nil && year.Modifier.IsValid() {
yearStr := strconv.Itoa(year.Value)
startOfYear := yearStr + "-01-01"
endOfYear := yearStr + "-12-31"

switch year.Modifier {
case models.CriterionModifierEquals:
// between yyyy-01-01 and yyyy-12-31
f.addWhere(col+" >= ?", startOfYear)
f.addWhere(col+" <= ?", endOfYear)
case models.CriterionModifierNotEquals:
// outside of yyyy-01-01 to yyyy-12-31
f.addWhere(col+" < ? OR "+col+" > ?", startOfYear, endOfYear)
case models.CriterionModifierGreaterThan:
// > yyyy-12-31
f.addWhere(col+" > ?", endOfYear)
case models.CriterionModifierLessThan:
// < yyyy-01-01
f.addWhere(col+" < ?", startOfYear)
}
clause, args := getIntCriterionWhereClause("cast(strftime('%Y', "+col+") as int)", *year)
f.addWhere(clause, args...)
}
}
}

func performerAgeFilterCriterionHandler(age *models.IntCriterionInput) criterionHandlerFunc {
return func(f *filterBuilder) {
if age != nil && age.Modifier.IsValid() {
var op string

switch age.Modifier {
case models.CriterionModifierEquals:
op = "=="
case models.CriterionModifierNotEquals:
op = "!="
case models.CriterionModifierGreaterThan:
op = ">"
case models.CriterionModifierLessThan:
op = "<"
}

if op != "" {
f.addWhere("cast(IFNULL(strftime('%Y.%m%d', performers.death_date), strftime('%Y.%m%d', 'now')) - strftime('%Y.%m%d', performers.birthdate) as int) "+op+" ?", age.Value)
}
clause, args := getIntCriterionWhereClause(
"cast(IFNULL(strftime('%Y.%m%d', performers.death_date), strftime('%Y.%m%d', 'now')) - strftime('%Y.%m%d', performers.birthdate) as int)",
*age,
)
f.addWhere(clause, args...)
}
}
}
Expand Down
32 changes: 24 additions & 8 deletions pkg/sqlite/performer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ func TestPerformerQueryEthnicityAndRating(t *testing.T) {
},
And: &models.PerformerFilterType{
Rating: &models.IntCriterionInput{
Value: int(performerRating.Int64),
Exact: int(performerRating.Int64),
Upper: int(performerRating.Int64),
Lower: int(performerRating.Int64),
Modifier: models.CriterionModifierEquals,
},
},
Expand Down Expand Up @@ -175,7 +177,9 @@ func TestPerformerQueryPathNotRating(t *testing.T) {
}

ratingCriterion := models.IntCriterionInput{
Value: int(performerRating.Int64),
Exact: int(performerRating.Int64),
Upper: int(performerRating.Int64),
Lower: int(performerRating.Int64),
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -341,7 +345,9 @@ func TestPerformerDestroyPerformerImage(t *testing.T) {
func TestPerformerQueryAge(t *testing.T) {
const age = 19
ageCriterion := models.IntCriterionInput{
Value: age,
Exact: age,
Upper: age,
Lower: age,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -553,7 +559,9 @@ func TestPerformerQueryTags(t *testing.T) {
func TestPerformerQueryTagCount(t *testing.T) {
const tagCount = 1
tagCountCriterion := models.IntCriterionInput{
Value: tagCount,
Exact: tagCount,
Upper: tagCount,
Lower: tagCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -594,7 +602,9 @@ func verifyPerformersTagCount(t *testing.T, tagCountCriterion models.IntCriterio
func TestPerformerQuerySceneCount(t *testing.T) {
const sceneCount = 1
sceneCountCriterion := models.IntCriterionInput{
Value: sceneCount,
Exact: sceneCount,
Upper: sceneCount,
Lower: sceneCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -635,7 +645,9 @@ func verifyPerformersSceneCount(t *testing.T, sceneCountCriterion models.IntCrit
func TestPerformerQueryImageCount(t *testing.T) {
const imageCount = 1
imageCountCriterion := models.IntCriterionInput{
Value: imageCount,
Exact: imageCount,
Upper: imageCount,
Lower: imageCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -685,7 +697,9 @@ func verifyPerformersImageCount(t *testing.T, imageCountCriterion models.IntCrit
func TestPerformerQueryGalleryCount(t *testing.T) {
const galleryCount = 1
galleryCountCriterion := models.IntCriterionInput{
Value: galleryCount,
Exact: galleryCount,
Upper: galleryCount,
Lower: galleryCount,
Modifier: models.CriterionModifierEquals,
}

Expand Down Expand Up @@ -809,7 +823,9 @@ func TestPerformerStashIDs(t *testing.T) {
func TestPerformerQueryRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Exact: rating,
Upper: rating,
Lower: rating,
Modifier: models.CriterionModifierEquals,
}

Expand Down
13 changes: 4 additions & 9 deletions pkg/sqlite/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,9 @@ func (qb *queryBuilder) addFilter(f *filterBuilder) {

func (qb *queryBuilder) handleIntCriterionInput(c *models.IntCriterionInput, column string) {
if c != nil {
clause, count := getIntCriterionWhereClause(column, *c)
clause, args := getIntCriterionWhereClause(column, *c)
qb.addWhere(clause)
if count == 1 {
qb.addArg(c.Value)
}
qb.addArg(args...)
}
}

Expand Down Expand Up @@ -192,12 +190,9 @@ func (qb *queryBuilder) handleStringCriterionInput(c *models.StringCriterionInpu

func (qb *queryBuilder) handleCountCriterion(countFilter *models.IntCriterionInput, primaryTable, joinTable, primaryFK string) {
if countFilter != nil {
clause, count := getCountCriterionClause(primaryTable, joinTable, primaryFK, *countFilter)

if count == 1 {
qb.addArg(countFilter.Value)
}
clause, args := getCountCriterionClause(primaryTable, joinTable, primaryFK, *countFilter)

qb.addWhere(clause)
qb.addArg(args...)
}
}
Loading

0 comments on commit f0fe2cc

Please sign in to comment.