mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Handle NULL in regex criteria (#1208)
This commit is contained in:
@@ -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, "?")
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 + ") = '')")
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user