zippoxer / bow

Bow - Minimal embedded database powered by Badger
MIT License
224 stars 15 forks source link

Bug: iterator doesn't flush the object #12

Open isbm opened 5 years ago

isbm commented 5 years ago

I am still not sure if that is a bug or undocumented wrong usage, but so far I think this should not happen. Any help appreciate.

Setup

For example, if I have struct like this:

type SomeEntry struct {
    Id string `bow:key`
    Names map[string]string
}

... // Here we do all inits and stuff (skipped)

func (se *SomeEntry) AddName(name string, explanation string) {
    se.Names[name] = string
}

So then I want to sort of accumulate Names map by re-visiting Bucket, fetching an object by an Id and add another key/vale to this Names map, then put that object back to the Bucket. Pretty straight-forward. If I have sometimes one name, sometime two names that are related to the entry, then it should appear per object in the bucket accordingly. Right?

To fetch the object I do this:

var entry SomeEntry
iterator := db.Bucket(someName).Iter()
defer iterator.Close()
for iterator.Next(&entry) {
    // do something with the entry, e.g. display Names
}

So then myobj.Names should have that map and in that loop I expect map-per-entry.

Problem

Problem is, that that map is always filled with other "garbage" — entries that already appeared elsewhere and does not belong to this particular entry. What I found is, that the map is kind of shared for the iterator.Next during re-filling the data to it, and so is not "flushed" in order to get filled in with the original data from the database, but the data is like written over the old one.

Workaround (works)

To workaround this, I've added the following method to my SomeEntry:

func (se *SomeEntry) Flush() {
    *se = *(&SomeEntry{})
}

This basically kills all the data inside the current struct instance. And then when I iterate while fetching, I call that method at the end, so then the Next() can re-fill the content properly.

Question

Is this a bug or a feature? :wink:

In case it is a bug, Next should actually either do it internally or require Flush (or reset or whatever) method from the structs. Not sure though...

zippoxer commented 4 years ago

Hi @isbm

You write well, maybe start a blog? 😋

Is this a bug? A feature?

Well... Your use-case is literally in the documentation. I guess that's not a feature then.

Will be fixing it this week hopefully. Likely to be a single-line change, just to ensure bow makes maps even if they ain't nil.

Thanks for your report!