Skip to content

Commit

Permalink
Fix exclude behaviour for stringListCriterionHandlerBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
WithoutPants committed Jun 11, 2024
1 parent a387cc2 commit 6f45b9e
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 3 deletions.
37 changes: 34 additions & 3 deletions pkg/sqlite/criterion_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,20 +517,51 @@ func (m *countCriterionHandlerBuilder) handler(criterion *models.IntCriterionInp

// handler for StringCriterion for string list fields
type stringListCriterionHandlerBuilder struct {
primaryTable string
// foreign key of the primary object on the join table
primaryFK string
// table joining primary and foreign objects
joinTable string
// string field on the join table
stringColumn string

addJoinTable func(f *filterBuilder)
addJoinTable func(f *filterBuilder)
excludeHandler func(f *filterBuilder, criterion *models.StringCriterionInput)
}

func (m *stringListCriterionHandlerBuilder) handler(criterion *models.StringCriterionInput) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if criterion != nil {
m.addJoinTable(f)
if criterion.Modifier == models.CriterionModifierExcludes {
// special handling for excludes
if m.excludeHandler != nil {
m.excludeHandler(f, criterion)
return
}

stringCriterionHandler(criterion, m.joinTable+"."+m.stringColumn)(ctx, f)
// excludes all of the provided values
// need to use actual join table name for this
// <primaryTable>.id NOT IN (select <joinTable>.<primaryFK> from <joinTable> where <joinTable>.<foreignFK> in <values>)
whereClause := utils.StrFormat("{primaryTable}.id NOT IN (SELECT {joinTable}.{primaryFK} from {joinTable} where {joinTable}.{stringColumn} LIKE ?)",
utils.StrFormatMap{
"primaryTable": m.primaryTable,
"joinTable": m.joinTable,
"primaryFK": m.primaryFK,
"stringColumn": m.stringColumn,
},
)

f.addWhere(whereClause, "%"+criterion.Value+"%")

// TODO - should we also exclude null values?
// m.addJoinTable(f)
// stringCriterionHandler(&models.StringCriterionInput{
// Modifier: models.CriterionModifierNotNull,
// }, m.joinTable+"."+m.stringColumn)(ctx, f)
} else {
m.addJoinTable(f)
stringCriterionHandler(criterion, m.joinTable+"."+m.stringColumn)(ctx, f)
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/gallery_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func (qb *galleryFilterHandler) criterionHandler() criterionHandler {

func (qb *galleryFilterHandler) urlsCriterionHandler(url *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: galleryTable,
primaryFK: galleryIDColumn,
joinTable: galleriesURLsTable,
stringColumn: galleriesURLColumn,
addJoinTable: func(f *filterBuilder) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/image_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ func (qb *imageFilterHandler) missingCriterionHandler(isMissing *string) criteri

func (qb *imageFilterHandler) urlsCriterionHandler(url *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: imageTable,
primaryFK: imageIDColumn,
joinTable: imagesURLsTable,
stringColumn: imageURLColumn,
addJoinTable: func(f *filterBuilder) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/movies_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ func (qb *movieFilterHandler) missingCriterionHandler(isMissing *string) criteri

func (qb *movieFilterHandler) urlsCriterionHandler(url *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: movieTable,
primaryFK: movieIDColumn,
joinTable: movieURLsTable,
stringColumn: movieURLColumn,
addJoinTable: func(f *filterBuilder) {
Expand Down
50 changes: 50 additions & 0 deletions pkg/sqlite/movies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,56 @@ func TestMovieQueryURL(t *testing.T) {
verifyMovieQuery(t, filter, verifyFn)
}

func TestMovieQueryURLExcludes(t *testing.T) {
withRollbackTxn(func(ctx context.Context) error {
mqb := db.Movie

// create movie with two URLs
movie := models.Movie{
Name: "TestMovieQueryURLExcludes",
URLs: models.NewRelatedStrings([]string{
"aaa",
"bbb",
}),
}

err := mqb.Create(ctx, &movie)

if err != nil {
return fmt.Errorf("Error creating movie: %w", err)
}

// query for movies that exclude the URL "aaa"
urlCriterion := models.StringCriterionInput{
Value: "aaa",
Modifier: models.CriterionModifierExcludes,
}

nameCriterion := models.StringCriterionInput{
Value: movie.Name,
Modifier: models.CriterionModifierEquals,
}

filter := models.MovieFilterType{
URL: &urlCriterion,
Name: &nameCriterion,
}

movies := queryMovie(ctx, t, mqb, &filter, nil)
assert.Len(t, movies, 0, "Expected no movies to be found")

// query for movies that exclude the URL "ccc"
urlCriterion.Value = "ccc"
movies = queryMovie(ctx, t, mqb, &filter, nil)

if assert.Len(t, movies, 1, "Expected one movie to be found") {
assert.Equal(t, movie.Name, movies[0].Name)
}

return nil
})
}

func verifyMovieQuery(t *testing.T, filter models.MovieFilterType, verifyFn func(s *models.Movie)) {
withTxn(func(ctx context.Context) error {
t.Helper()
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/performer_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ func (qb *performerFilterHandler) performerAgeFilterCriterionHandler(age *models

func (qb *performerFilterHandler) aliasCriterionHandler(alias *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: performerTable,
primaryFK: performerIDColumn,
joinTable: performersAliasesTable,
stringColumn: performerAliasColumn,
addJoinTable: func(f *filterBuilder) {
Expand Down
14 changes: 14 additions & 0 deletions pkg/sqlite/scene_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ func (qb *sceneFilterHandler) isMissingCriterionHandler(isMissing *string) crite

func (qb *sceneFilterHandler) urlsCriterionHandler(url *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: sceneTable,
primaryFK: sceneIDColumn,
joinTable: scenesURLsTable,
stringColumn: sceneURLColumn,
addJoinTable: func(f *filterBuilder) {
Expand All @@ -368,12 +370,24 @@ func (qb *sceneFilterHandler) getMultiCriterionHandlerBuilder(foreignTable, join

func (qb *sceneFilterHandler) captionCriterionHandler(captions *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: sceneTable,
primaryFK: sceneIDColumn,
joinTable: videoCaptionsTable,
stringColumn: captionCodeColumn,
addJoinTable: func(f *filterBuilder) {
qb.addSceneFilesTable(f)
f.addLeftJoin(videoCaptionsTable, "", "video_captions.file_id = scenes_files.file_id")
},
excludeHandler: func(f *filterBuilder, criterion *models.StringCriterionInput) {
excludeClause := `scenes.id NOT IN (
SELECT scenes_files.scene_id from scenes_files
INNER JOIN video_captions on video_captions.file_id = scenes_files.file_id
WHERE video_captions.language_code LIKE ?
)`
f.addWhere(excludeClause, criterion.Value)

// TODO - should we also exclude null values?
},
}

return h.handler(captions)
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/studio_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ func (qb *studioFilterHandler) parentCriterionHandler(parents *models.MultiCrite

func (qb *studioFilterHandler) aliasCriterionHandler(alias *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: studioTable,
primaryFK: studioIDColumn,
joinTable: studioAliasesTable,
stringColumn: studioAliasColumn,
addJoinTable: func(f *filterBuilder) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/tag_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ func (qb *tagFilterHandler) criterionHandler() criterionHandler {

func (qb *tagFilterHandler) aliasCriterionHandler(alias *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: tagTable,
primaryFK: tagIDColumn,
joinTable: tagAliasesTable,
stringColumn: tagAliasColumn,
addJoinTable: func(f *filterBuilder) {
Expand Down

0 comments on commit 6f45b9e

Please sign in to comment.