Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cursor.Prev() out of range issue v1.3.9 #733

Closed
axww opened this issue Apr 21, 2024 · 4 comments · Fixed by #734
Closed

Cursor.Prev() out of range issue v1.3.9 #733

axww opened this issue Apr 21, 2024 · 4 comments · Fixed by #734

Comments

@axww
Copy link

axww commented Apr 21, 2024

Hi, I met an issue during dev. Here's my sample code:

package main

import (
	"fmt"
	"log"

	bolt "go.etcd.io/bbolt"
)

func main() {

	aDb, dbErr := bolt.Open("a.db", 0600, nil)
	if dbErr != nil {
		log.Fatal(dbErr)
	}
	defer aDb.Close()

	aDb.Batch(func(tx *bolt.Tx) error {
		// Create data
		b, _ := tx.CreateBucketIfNotExists([]byte("test"))
		b.Put([]byte("1"), nil)
		b.Put([]byte("2"), nil)
		b.Put([]byte("3"), nil)
		// Next test
		fmt.Println("=== Next test ===")
		cn := b.Cursor()
		cn.Seek([]byte("2")) //2
		cn.Next()            // 3
		cn.Next()            // nil (Cursor stops at 3)
		kn, _ := cn.Prev()   // 2
		fmt.Println(string(kn))
		// Prev test
		fmt.Println("=== Prev test ===")
		cp := b.Cursor()
		cp.Seek([]byte("2")) //2
		cp.Prev()            // 1
		cp.Prev()            // nil (Cursor out of range)
		kp, _ := cp.Next()   // Should be 2 but nil
		fmt.Println(string(kp))
		// End
		return nil
	})
}

The output of the program:

=== Next test ===
2
=== Prev test ===

As you can see I put 3 rows "1", "2" and "3" into the bucket.
Both of "Next test" and "Prev test", I set cursor at "2" initially.

In "Next test", I move cursor to "3", then run Next() again, it returns nil.
Then I run Prev(), the cursor targets to "2".

In "Prev test", I move cursor to "1", then run Prev() again, it returns nil.
Then I run Next(), the cursor targets to nil.

Whatever how many Next() I added in "Prev test", the cursor still targes to nil.
It seems after Cursor.Prev() out of range, it stucks there and can not be use anymore.

I don't know if this is a bug or a correct design, but it's strange.
Do you consider make these 2 situations have similiar behavior?

Thank you very much!
Best

@ahrtr
Copy link
Member

ahrtr commented Apr 21, 2024

Thanks @axww for raising this issue.

It's a minor issue. Usually when you have already reached the beginning, you should call First if you want to iterate over the elements in the reverse direction by call Next.

But I agree that users should be able to call Next directly without calling First in such scenario. Fixed it in #734.

@ahrtr
Copy link
Member

ahrtr commented May 2, 2024

Open to track the backport effort

@ahrtr
Copy link
Member

ahrtr commented May 3, 2024

Done.

@ahrtr ahrtr closed this as completed May 3, 2024
@ahrtr
Copy link
Member

ahrtr commented May 3, 2024

The fix will be included in 1.3.10

ahrtr added a commit to openkvlab/boltdb that referenced this issue Jul 23, 2024
… by call Next when it has already reached the beginning

Refer to etcd-io/bbolt#733

Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
2 participants