Handle NULL in regex criteria (#1208)

This commit is contained in:
WithoutPants
2021-03-16 11:13:14 +11:00
committed by GitHub
parent f7cd9cb00d
commit 7e6127975d
7 changed files with 73 additions and 6 deletions

View File

@@ -311,13 +311,13 @@ func stringCriterionHandler(c *models.StringCriterionInput, column string) crite
f.setError(err)
return
}
f.addWhere(column+" regexp ?", c.Value)
f.addWhere(fmt.Sprintf("(%s IS NOT NULL AND %[1]s regexp ?)", column), c.Value)
case models.CriterionModifierNotMatchesRegex:
if _, err := regexp.Compile(c.Value); err != nil {
f.setError(err)
return
}
f.addWhere(column+" NOT regexp ?", c.Value)
f.addWhere(fmt.Sprintf("(%s IS NULL OR %[1]s NOT regexp ?)", column), c.Value)
default:
clause, count := getSimpleCriterionClause(modifier, "?")

View File

@@ -530,7 +530,7 @@ func TestStringCriterionHandlerMatchesRegex(t *testing.T) {
}, column))
assert.Len(f.whereClauses, 1)
assert.Equal(fmt.Sprintf("%[1]s regexp ?", column), f.whereClauses[0].sql)
assert.Equal(fmt.Sprintf("(%s IS NOT NULL AND %[1]s regexp ?)", column), f.whereClauses[0].sql)
assert.Len(f.whereClauses[0].args, 1)
assert.Equal(validValue, f.whereClauses[0].args[0])
@@ -558,7 +558,7 @@ func TestStringCriterionHandlerNotMatchesRegex(t *testing.T) {
}, column))
assert.Len(f.whereClauses, 1)
assert.Equal(fmt.Sprintf("%[1]s NOT regexp ?", column), f.whereClauses[0].sql)
assert.Equal(fmt.Sprintf("(%s IS NULL OR %[1]s NOT regexp ?)", column), f.whereClauses[0].sql)
assert.Len(f.whereClauses[0].args, 1)
assert.Equal(validValue, f.whereClauses[0].args[0])

View File

@@ -228,6 +228,46 @@ func verifyPerformerAge(t *testing.T, ageCriterion models.IntCriterionInput) {
})
}
func TestPerformerQueryCareerLength(t *testing.T) {
const value = "2005"
careerLengthCriterion := models.StringCriterionInput{
Value: value,
Modifier: models.CriterionModifierEquals,
}
verifyPerformerCareerLength(t, careerLengthCriterion)
careerLengthCriterion.Modifier = models.CriterionModifierNotEquals
verifyPerformerCareerLength(t, careerLengthCriterion)
careerLengthCriterion.Modifier = models.CriterionModifierMatchesRegex
verifyPerformerCareerLength(t, careerLengthCriterion)
careerLengthCriterion.Modifier = models.CriterionModifierNotMatchesRegex
verifyPerformerCareerLength(t, careerLengthCriterion)
}
func verifyPerformerCareerLength(t *testing.T, criterion models.StringCriterionInput) {
withTxn(func(r models.Repository) error {
qb := r.Performer()
performerFilter := models.PerformerFilterType{
CareerLength: &criterion,
}
performers, _, err := qb.Query(&performerFilter, nil)
if err != nil {
t.Errorf("Error querying performer: %s", err.Error())
}
for _, performer := range performers {
cl := performer.CareerLength
verifyNullString(t, cl, criterion)
}
return nil
})
}
func queryPerformers(t *testing.T, qb models.PerformerReader, performerFilter *models.PerformerFilterType, findFilter *models.FindFilterType) []*models.Performer {
performers, _, err := qb.Query(performerFilter, findFilter)
if err != nil {

View File

@@ -1,6 +1,7 @@
package sqlite
import (
"fmt"
"regexp"
"github.com/stashapp/stash/pkg/models"
@@ -127,14 +128,14 @@ func (qb *queryBuilder) handleStringCriterionInput(c *models.StringCriterionInpu
qb.err = err
return
}
qb.addWhere(column + " regexp ?")
qb.addWhere(fmt.Sprintf("(%s IS NOT NULL AND %[1]s regexp ?)", column))
qb.addArg(c.Value)
case models.CriterionModifierNotMatchesRegex:
if _, err := regexp.Compile(c.Value); err != nil {
qb.err = err
return
}
qb.addWhere(column + " NOT regexp ?")
qb.addWhere(fmt.Sprintf("(%s IS NULL OR %[1]s NOT regexp ?)", column))
qb.addArg(c.Value)
case models.CriterionModifierIsNull:
qb.addWhere("(" + column + " IS NULL OR TRIM(" + column + ") = '')")

View File

@@ -356,6 +356,17 @@ func verifyNullString(t *testing.T, value sql.NullString, criterion models.Strin
if criterion.Modifier == models.CriterionModifierNotEquals {
assert.NotEqual(criterion.Value, value.String)
}
if criterion.Modifier == models.CriterionModifierMatchesRegex {
assert.True(value.Valid)
assert.Regexp(regexp.MustCompile(criterion.Value), value)
}
if criterion.Modifier == models.CriterionModifierNotMatchesRegex {
if !value.Valid {
// correct
return
}
assert.NotRegexp(regexp.MustCompile(criterion.Value), value)
}
}
func verifyString(t *testing.T, value string, criterion models.StringCriterionInput) {

View File

@@ -587,6 +587,15 @@ func getPerformerBirthdate(index int) string {
return birthdate.Format("2006-01-02")
}
func getPerformerCareerLength(index int) *string {
if index%5 == 0 {
return nil
}
ret := fmt.Sprintf("20%2d", index)
return &ret
}
//createPerformers creates n performers with plain Name and o performers with camel cased NaMe included
func createPerformers(pqb models.PerformerReaderWriter, n int, o int) error {
const namePlain = "Name"
@@ -613,6 +622,11 @@ func createPerformers(pqb models.PerformerReaderWriter, n int, o int) error {
},
}
careerLength := getPerformerCareerLength(i)
if careerLength != nil {
performer.CareerLength = models.NullString(*careerLength)
}
created, err := pqb.Create(performer)
if err != nil {

View File

@@ -20,6 +20,7 @@
* Added Rescan button to scene, image, gallery details overflow button.
### 🐛 Bug fixes
* Fix SQL error when filtering nullable string fields with regex.
* Fix incorrect folders being excluded during scanning.
* Filter out streaming resolution options that are over the maximum streaming resolution.
* Fix `cover.jpg` not being detected as cover image when in sub-directory.