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

Charm KV .Keys() function returning duplicate keys #157

Closed
huntlyc opened this issue Jul 18, 2022 · 3 comments
Closed

Charm KV .Keys() function returning duplicate keys #157

huntlyc opened this issue Jul 18, 2022 · 3 comments

Comments

@huntlyc
Copy link
Contributor

huntlyc commented Jul 18, 2022

Issue

Listing out the keys using the the db.Keys() function gives me wrong results.

If I run a small program that creates 3 kv pairs and then use db.Keys() to list them out I get a duplicate key value.

I ran my example program to generate the keys, then used the charm cli tool to list my keys out, then run the program again which shows the difference between .Keys() and .View() functions:

➜  charm-test charm kv list @charm-kv-keys-test-db      
key1	value1
key2	value2
key3	value3
➜  charm-test go run main.go                      
Charm kv .Keys()
0: key3
1: key2
2: key3
Charm kv .View() to list keys and values
key1 - value1
key2 - value2
key3 - value3

Example program to demonstrate

package main
import (
	"github.com/charmbracelet/charm/kv"
    "github.com/dgraph-io/badger/v3"
    "fmt"
    "log"
)

func main(){
    // Open a database (or create one if it doesn’t exist)
    db, err := kv.OpenWithDefaults("charm-kv-keys-test-db")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()


    // Save some data
    if err := db.Set([]byte("key1"), []byte("value1")); err != nil {
        log.Fatal(err)
    }

    if err := db.Set([]byte("key2"), []byte("value2")); err != nil {
        log.Fatal(err)
    }

    if err := db.Set([]byte("key3"), []byte("value3")); err != nil {
        log.Fatal(err)
    }

    fmt.Println("Charm kv .Keys()")
    if keys,err := db.Keys(); err != nil{
        log.Fatal(err)
    }else{
        for i,k := range keys{
            fmt.Printf("%d: %s\n", i, string(k))
        }
    }

    fmt.Println("Charm kv .View() to list keys and values")
    // Go full-blown Badger and use transactions to list values and keys
	db.View(func(txn *badger.Txn) error {
		opts := badger.DefaultIteratorOptions
		opts.PrefetchSize = 10
		it := txn.NewIterator(opts)
		defer it.Close() //nolint:errcheck
		for it.Rewind(); it.Valid(); it.Next() {
			item := it.Item()
			k := item.Key()
			err := item.Value(func(v []byte) error {
				fmt.Printf("%s - %s\n", k, v)
				return nil
			})
			if err != nil {
				panic(err)
			}
		}
		return nil
	})
}

Possible fix?

Disclaimer: I only started looking at Go last week, so could be that I'm doing something dumb here!

However, when running a debug session to try and figure it out, I did find that I could get it to work if I changed the following line in the kv.go file from

ks = append(ks, it.Item().Key())

to

ks = append(ks, it.Item().KeyCopy(nil))
@aymanbagabas
Copy link
Member

@huntlyc thank you for reporting this issue. Would you mind creating a PR for your fix?

@huntlyc
Copy link
Contributor Author

huntlyc commented Jul 19, 2022

@aymanbagabas - yeah, can do

@aymanbagabas
Copy link
Member

Thank you @huntlyc! The fix gonna be part of next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants