Skip to content
This repository has been archived by the owner on Mar 9, 2019. It is now read-only.

Deleting a non-existing key throws ErrIncompatibleValue #349

Open
vincent-petithory opened this issue Apr 13, 2015 · 0 comments · Fixed by etcd-io/bbolt#23
Open

Deleting a non-existing key throws ErrIncompatibleValue #349

vincent-petithory opened this issue Apr 13, 2015 · 0 comments · Fixed by etcd-io/bbolt#23

Comments

@vincent-petithory
Copy link
Contributor

I'm not sure if this is really a bug, but I've been unable to explain myself the following behavior.

In a bucket, when trying to delete a non-existing key, which has a common prefix with a subbucket, the cursor in https://github.com/boltdb/bolt/blob/master/bucket.go#L315 seems to seek mistakenly on the subbucket, thus throwing a ErrIncompatibleValue.

Here's a failing test illustrating this:

// Ensure that deleting a non-existing key doesn't try to delete a bucket with a common prefix.
func TestCursor_DeleteNonExistingKey_CommonPrefixBucket(t *testing.T) {
    db := NewTestDB()
    defer db.Close()

    prefix := make([]byte, 16)
    n, err := rand.Read(prefix)
    ok(t, err)
    assert(t, n == 16, "failed to read 16 bytes")

    bucketSuffix := []byte(".shapes") // .n_shape < .shapes

    db.Update(func(tx *bolt.Tx) error {
        b, err := tx.CreateBucket([]byte("widgets"))
        ok(t, err)
        // Create an empty subbucket which has prefix as prefix in its key
        _, err = b.CreateBucketIfNotExists(append(prefix, bucketSuffix...))
        ok(t, err)
        return nil
    })

    db.Update(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("widgets"))
        // Delete a non-existing key which has kPrefix as prefix
        err := b.Delete(append(prefix, []byte(".n_shapes")...))
        ok(t, err)
        // Delete the empty subbucket
        err = b.DeleteBucket(append(prefix, bucketSuffix...))
        ok(t, err)
        return nil
    })
}

The fact that .n_shapes < .shapes matters. If bucketSuffix := []byte(".items") instead, the test passes, because the subbucket is virtually ordered before the non-existing searched key.

Thanks in advance for any enlightenment :)

heyitsanthony pushed a commit to heyitsanthony/bolt that referenced this issue Aug 11, 2017
Doc for Bucket.Delete says that a Delete() on non-existing key is a
no-op. Right now it tries to delete the next key returned by the
cursor. Fix this by checking for key equivalence before deletion.

 Fixes boltdb#349

Signed-off-by: Pavel Borzenkov <pavel.borzenkov@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant