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

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

@huntlyc

Description

@huntlyc

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))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions