Skip to content

Commit

Permalink
Fix issue in fetching the max key when keys are substrings of each other
Browse files Browse the repository at this point in the history
Authored by: Marty Schoch <[email protected]>
See conversation on: blevesearch/bleve#1096

Change-Id: I9a63f6bd5e0605ac3a48ba42076bbf6959f1448e
Reviewed-on: http://review.couchbase.org/103303
Well-Formed: Build Bot <[email protected]>
Reviewed-by: Steve Yen <[email protected]>
Reviewed-by: Sreekanth Sivasankaran <[email protected]>
Tested-by: Abhinav Dangeti <[email protected]>
  • Loading branch information
abhinavdangeti committed Jan 7, 2019
1 parent dd17fb8 commit 28880ab
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 17 deletions.
40 changes: 23 additions & 17 deletions fst.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func (f *FST) Reader() (*Reader, error) {
return &Reader{f: f}, nil
}

func (f *FST) getMinMaxKey(comparator func(byte, byte) bool) ([]byte, error) {
func (f *FST) GetMinKey() ([]byte, error) {
var rv []byte

curr := f.decoder.getRoot()
Expand All @@ -253,34 +253,40 @@ func (f *FST) getMinMaxKey(comparator func(byte, byte) bool) ([]byte, error) {
}

for !state.Final() {
lastTransition := state.TransitionAt(0)
numTransitions := state.NumTransitions()
for i := 1; i < numTransitions; i++ {
transition := state.TransitionAt(i)
if comparator(transition, lastTransition) {
lastTransition = transition
}
}

_, curr, _ = state.TransitionFor(lastTransition)
nextTrans := state.TransitionAt(0)
_, curr, _ = state.TransitionFor(nextTrans)
state, err = f.decoder.stateAt(curr, state)
if err != nil {
return nil, err
}

rv = append(rv, lastTransition)
rv = append(rv, nextTrans)
}

return rv, nil
}

func (f *FST) GetMinKey() ([]byte, error) {
return f.getMinMaxKey(func (x byte, y byte) bool {return x < y})
}
func (f *FST) GetMaxKey() ([]byte, error) {
var rv []byte

curr := f.decoder.getRoot()
state, err := f.decoder.stateAt(curr, nil)
if err != nil {
return nil, err
}

func (f *FST) GetMaxKey() ([]byte, error) {
return f.getMinMaxKey(func (x byte, y byte) bool {return x > y})
for state.NumTransitions() > 0 {
nextTrans := state.TransitionAt(state.NumTransitions() - 1)
_, curr, _ = state.TransitionFor(nextTrans)
state, err = f.decoder.stateAt(curr, state)
if err != nil {
return nil, err
}

rv = append(rv, nextTrans)
}

return rv, nil
}

// A Reader is meant for a single threaded use
Expand Down
56 changes: 56 additions & 0 deletions vellum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,59 @@ func benchmarkBigKey(b *testing.B, n int) {
}
}
}

func TestMaxWithSubstring(t *testing.T) {
var buf bytes.Buffer
builder, err := New(&buf, nil)
if err != nil {
t.Fatal(err)
}

err = builder.Insert([]byte("1"), 1)
if err != nil {
t.Fatal(err)
}

err = builder.Insert([]byte("11"), 1)
if err != nil {
t.Fatal(err)
}

err = builder.Insert([]byte("9"), 9)
if err != nil {
t.Fatal(err)
}

err = builder.Insert([]byte("99"), 99)
if err != nil {
t.Fatal(err)
}

err = builder.Close()
if err != nil {
t.Fatal(err)
}

fst, err := Load(buf.Bytes())
if err != nil {
t.Fatal(err)
}

mink, err := fst.GetMinKey()
if err != nil {
t.Fatal(err)
}

if string(mink) != "1" {
t.Fatalf("expected max key 1, got %s", string(mink))
}

maxk, err := fst.GetMaxKey()
if err != nil {
t.Fatal(err)
}

if string(maxk) != "99" {
t.Fatalf("expected max key 99, got %s", string(maxk))
}
}

0 comments on commit 28880ab

Please sign in to comment.