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

Cursor inconsistent when mixing cursor.Delete() with Put() in same transaction #357

@thatguystone

Description

@thatguystone

This one is probably best described with a (failing) test case:

func TestCursor_DeleteInAddTransaction(t *testing.T) {
    db := NewTestDB()
    defer db.Close()

    const count = 10

    db.Update(func(tx *bolt.Tx) error {
        b, _ := tx.CreateBucket([]byte("widgets"))
        for i := 0; i < count; i++ {
            k := make([]byte, 8)
            binary.BigEndian.PutUint64(k, uint64(i))
            b.Put(k, make([]byte, 100))
        }

        c := b.Cursor()
        for key, _ := c.First(); key != nil; key, _ = c.Next() {
            if err := c.Delete(); err != nil {
                return err
            }
        }

        return nil
    })

    db.View(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("widgets"))
        equals(t, 0, b.Stats().KeyN)
        return nil
    })
}

It should delete all of the inserted keys, but instead, the following keys remain: 1, 3, 5, 7, 9.

This also seems to be the case when there's a pre-existing set of keys and a single key is put (for example):

func TestCursor_DeleteMultipleTransactions(t *testing.T) {
    db := NewTestDB()
    defer db.Close()

    const count = 10

    db.Update(func(tx *bolt.Tx) error {
        b, _ := tx.CreateBucket([]byte("widgets"))
        for i := 0; i < count; i++ {
            k := make([]byte, 8)
            binary.BigEndian.PutUint64(k, uint64(i))
            b.Put(k, make([]byte, 100))
        }
        return nil
    })

    db.Update(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("widgets"))

        k := make([]byte, 8)
        binary.BigEndian.PutUint64(k, uint64(0))
        b.Put(k, make([]byte, 100))

        c := b.Cursor()
        for key, _ := c.First(); key != nil; key, _ = c.Next() {
            if err := c.Delete(); err != nil {
                return err
            }
        }

        return nil
    })

    db.View(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("widgets"))
        c := b.Cursor()
        for key, _ := c.First(); key != nil; key, _ = c.Next() {
            u := binary.BigEndian.Uint64(key)
            fmt.Println(u)
        }

        equals(t, 0, b.Stats().KeyN)
        return nil
    })
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions