mirror of https://github.com/perkeep/perkeep.git
search: Add ValueMatches{Int,Float} to PermanodeConstraint.
Adds constraints for int- and float-valued attributes. Change-Id: Ie8354f8ea12f604b45cf2fa6a7fb45170bab7e46
This commit is contained in:
parent
9c45ab99ad
commit
396c8a6211
|
@ -388,7 +388,7 @@ func (c *IntConstraint) intMatches(v int64) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// A FloatConstraint specifies constraints on an integer.
|
||||
// A FloatConstraint specifies constraints on a float.
|
||||
type FloatConstraint struct {
|
||||
// Min and Max are both optional and inclusive bounds.
|
||||
// Zero means don't check.
|
||||
|
@ -574,6 +574,14 @@ type PermanodeConstraint struct {
|
|||
// match the value against.
|
||||
ValueMatches *StringConstraint `json:"valueMatches,omitempty"`
|
||||
|
||||
// ValueMatchesInt optionally specifies an IntConstraint to match
|
||||
// the value against. Non-integer values will not match.
|
||||
ValueMatchesInt *IntConstraint `json:"valueMatchesInt,omitempty"`
|
||||
|
||||
// ValueMatchesFloat optionally specifies a FloatConstraint to match
|
||||
// the value against. Non-float values will not match.
|
||||
ValueMatchesFloat *FloatConstraint `json:"valueMatchesFloat,omitempty"`
|
||||
|
||||
// ValueInSet optionally specifies a sub-query which the value
|
||||
// (which must be a blobref) must be a part of.
|
||||
ValueInSet *Constraint `json:"valueInSet,omitempty"`
|
||||
|
@ -1008,11 +1016,15 @@ var numPermanodeFields = reflect.TypeOf(PermanodeConstraint{}).NumField()
|
|||
// hasValueConstraint returns true if one or more constraints that check an attribute's value are set.
|
||||
func (c *PermanodeConstraint) hasValueConstraint() bool {
|
||||
// If a field has been added or removed, update this after adding the new field to the return statement if necessary.
|
||||
const expectedFields = 12
|
||||
const expectedFields = 14
|
||||
if numPermanodeFields != expectedFields {
|
||||
panic(fmt.Sprintf("PermanodeConstraint field count changed (now %v rather than %v)", numPermanodeFields, expectedFields))
|
||||
}
|
||||
return c.Value != "" || c.ValueMatches != nil || c.ValueInSet != nil
|
||||
return c.Value != "" ||
|
||||
c.ValueMatches != nil ||
|
||||
c.ValueMatchesInt != nil ||
|
||||
c.ValueMatchesFloat != nil ||
|
||||
c.ValueInSet != nil
|
||||
}
|
||||
|
||||
func (c *PermanodeConstraint) blobMatches(s *search, br blob.Ref, bm camtypes.BlobMeta) (ok bool, err error) {
|
||||
|
@ -1145,6 +1157,16 @@ func (c *PermanodeConstraint) permanodeMatchesAttrVal(s *search, val string) (bo
|
|||
if c.ValueMatches != nil && !c.ValueMatches.stringMatches(val) {
|
||||
return false, nil
|
||||
}
|
||||
if c.ValueMatchesInt != nil {
|
||||
if i, err := strconv.ParseInt(val, 10, 64); err != nil || !c.ValueMatchesInt.intMatches(i) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
if c.ValueMatchesFloat != nil {
|
||||
if f, err := strconv.ParseFloat(val, 64); err != nil || !c.ValueMatchesFloat.floatMatches(f) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
if subc := c.ValueInSet; subc != nil {
|
||||
br, ok := blob.Parse(val) // TODO: use corpus's parse, or keep this as blob.Ref in corpus attr
|
||||
if !ok {
|
||||
|
|
|
@ -476,6 +476,64 @@ func TestQueryPermanodeAttrValueInSet(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
// Tests PermanodeConstraint.ValueMatchesInt.
|
||||
func TestQueryPermanodeValueMatchesInt(t *testing.T) {
|
||||
testQuery(t, func(qt *queryTest) {
|
||||
id := qt.id
|
||||
|
||||
p1 := id.NewPlannedPermanode("1")
|
||||
p2 := id.NewPlannedPermanode("2")
|
||||
p3 := id.NewPlannedPermanode("3")
|
||||
p4 := id.NewPlannedPermanode("4")
|
||||
p5 := id.NewPlannedPermanode("5")
|
||||
id.SetAttribute(p1, "x", "-5")
|
||||
id.SetAttribute(p2, "x", "0")
|
||||
id.SetAttribute(p3, "x", "2")
|
||||
id.SetAttribute(p4, "x", "10.0")
|
||||
id.SetAttribute(p5, "x", "abc")
|
||||
|
||||
sq := &SearchQuery{
|
||||
Constraint: &Constraint{
|
||||
Permanode: &PermanodeConstraint{
|
||||
Attr: "x",
|
||||
ValueMatchesInt: &IntConstraint{
|
||||
Min: -2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
qt.wantRes(sq, p2, p3)
|
||||
})
|
||||
}
|
||||
|
||||
// Tests PermanodeConstraint.ValueMatchesFloat.
|
||||
func TestQueryPermanodeValueMatchesFloat(t *testing.T) {
|
||||
testQuery(t, func(qt *queryTest) {
|
||||
id := qt.id
|
||||
|
||||
p1 := id.NewPlannedPermanode("1")
|
||||
p2 := id.NewPlannedPermanode("2")
|
||||
p3 := id.NewPlannedPermanode("3")
|
||||
p4 := id.NewPlannedPermanode("4")
|
||||
id.SetAttribute(p1, "x", "2.5")
|
||||
id.SetAttribute(p2, "x", "5.7")
|
||||
id.SetAttribute(p3, "x", "10")
|
||||
id.SetAttribute(p4, "x", "abc")
|
||||
|
||||
sq := &SearchQuery{
|
||||
Constraint: &Constraint{
|
||||
Permanode: &PermanodeConstraint{
|
||||
Attr: "x",
|
||||
ValueMatchesFloat: &FloatConstraint{
|
||||
Max: 6.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
qt.wantRes(sq, p1, p2)
|
||||
})
|
||||
}
|
||||
|
||||
// find permanodes matching a certain file query
|
||||
func TestQueryFileConstraint(t *testing.T) {
|
||||
testQuery(t, func(qt *queryTest) {
|
||||
|
|
Loading…
Reference in New Issue