pkg/client: return error for unindexed attr search

Calling 'GetPermanodesWithAttr', as currently written, will return an
empty list for any unindexed parameters.

Rather than always returning an empty list if the user asks for a
unindexed attribute, error out.

Also add documentation of this potential foot-gun for users of the
client.

Change-Id: Iadc1b5a00aa709584affb89a1397e82aaffb692f
This commit is contained in:
Euan Kemp 2018-07-25 00:53:27 -07:00
parent 7d198eed67
commit 13a8e94895
3 changed files with 52 additions and 0 deletions

View File

@ -716,6 +716,10 @@ func (c *Client) GetRecentPermanodes(ctx context.Context, req *search.RecentRequ
return res, nil
}
// GetPermanodesWithAttr searches for permanodes that match the given search request.
// The Fuzzy option in the request must not be set, and the Attribute option
// must be set.
// Only indexed attributes may be queried.
func (c *Client) GetPermanodesWithAttr(ctx context.Context, req *search.WithAttrRequest) (*search.WithAttrResponse, error) {
sr, err := c.SearchRoot()
if err != nil {

View File

@ -1031,6 +1031,9 @@ func (x *Index) SearchPermanodesWithAttr(ctx context.Context, dest chan<- blob.R
if request.Attribute == "" {
return errors.New("index: missing Attribute in SearchPermanodesWithAttr")
}
if !IsIndexedAttribute(request.Attribute) {
return fmt.Errorf("SearchPermanodesWithAttr: called with a non-indexed attribute %q", request.Attribute)
}
keyId, err := x.KeyId(ctx, request.Signer)
if err == sorted.ErrNotFound {

View File

@ -317,6 +317,7 @@ func Index(t *testing.T, initIdx func() *index.Index) {
t.Logf("set attribute %q", rootClaim)
pnChild := id.NewPermanode()
id.SetAttribute(pnChild, "unindexed", "lost in time and space")
br3 := id.SetAttribute(pnChild, "tag", "bar")
br3Time := id.LastTime()
t.Logf("set attribute %q", br3)
@ -536,6 +537,50 @@ func Index(t *testing.T, initIdx func() *index.Index) {
}
}
// SearchPermanodesWithAttr - match none with attr type "tag=nosuchtag"
{
ch := make(chan blob.Ref, 10)
req := &camtypes.PermanodeByAttrRequest{
Signer: id.SignerBlobRef,
Attribute: "tag",
Query: "nosuchtag",
}
err := id.Index.SearchPermanodesWithAttr(ctx, ch, req)
if err != nil {
t.Fatalf("SearchPermanodesWithAttr = %v", err)
}
var got []blob.Ref
for r := range ch {
got = append(got, r)
}
want := []blob.Ref{}
if len(got) != len(want) {
t.Errorf("SearchPermanodesWithAttr results differ.\n got: %q\nwant: %q",
got, want)
}
}
// SearchPermanodesWithAttr - error for unindexed attr
{
ch := make(chan blob.Ref, 10)
req := &camtypes.PermanodeByAttrRequest{
Signer: id.SignerBlobRef,
Attribute: "unindexed",
}
err := id.Index.SearchPermanodesWithAttr(ctx, ch, req)
if err != nil {
t.Fatalf("SearchPermanodesWithAttr = %v", err)
}
var got []blob.Ref
for r := range ch {
got = append(got, r)
}
want := []blob.Ref{}
if len(got) != len(want) {
t.Errorf("SearchPermanodesWithAttr results differ.\n got: %q\nwant: %q",
got, want)
}
}
// Delete value "pony" of type "title" (which does not actually exist) for pn
br4 := id.DelAttribute(pn, "title", "pony")
br4Time := id.LastTime()