mirror of https://github.com/tidwall/buntdb.git
Index pattern not always honored
When creating an index with CreateIndex, a pattern is used to specify the matching keys that should be stored in the index. It is therefore unexpected that items that do not match the pattern will be presented to the less function that is also supplied on CreateIndex. This change corrects that problem by applying the pattern in two paths previously not considered: 1. When an item is replaced in the database. 2. When an item is deleted from the database.
This commit is contained in:
parent
ae2bcacb06
commit
97feb53ded
18
buntdb.go
18
buntdb.go
|
@ -454,16 +454,22 @@ func (db *DB) SetConfig(config Config) error {
|
||||||
// will be replaced with the new one, and return the previous item.
|
// will be replaced with the new one, and return the previous item.
|
||||||
func (db *DB) insertIntoDatabase(item *dbItem) *dbItem {
|
func (db *DB) insertIntoDatabase(item *dbItem) *dbItem {
|
||||||
var pdbi *dbItem
|
var pdbi *dbItem
|
||||||
|
idxs := []*index{}
|
||||||
|
for _, idx := range db.idxs {
|
||||||
|
if idx.match(item.key) {
|
||||||
|
idxs = append(idxs, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
prev := db.keys.Set(item)
|
prev := db.keys.Set(item)
|
||||||
if prev != nil {
|
if prev != nil {
|
||||||
// A previous item was removed from the keys tree. Let's
|
// A previous item was removed from the keys tree. Let's
|
||||||
// fully delete this item from all indexes.
|
// fully delete this item from all indexes.
|
||||||
pdbi = prev.(*dbItem)
|
pdbi = prev.(*dbItem)
|
||||||
if pdbi.opts != nil && pdbi.opts.ex {
|
if pdbi.opts != nil && pdbi.opts.ex {
|
||||||
// Remove it from the exipres tree.
|
// Remove it from the expires tree.
|
||||||
db.exps.Delete(pdbi)
|
db.exps.Delete(pdbi)
|
||||||
}
|
}
|
||||||
for _, idx := range db.idxs {
|
for _, idx := range idxs {
|
||||||
if idx.btr != nil {
|
if idx.btr != nil {
|
||||||
// Remove it from the btree index.
|
// Remove it from the btree index.
|
||||||
idx.btr.Delete(pdbi)
|
idx.btr.Delete(pdbi)
|
||||||
|
@ -479,10 +485,7 @@ func (db *DB) insertIntoDatabase(item *dbItem) *dbItem {
|
||||||
// expires tree
|
// expires tree
|
||||||
db.exps.Set(item)
|
db.exps.Set(item)
|
||||||
}
|
}
|
||||||
for _, idx := range db.idxs {
|
for _, idx := range idxs {
|
||||||
if !idx.match(item.key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if idx.btr != nil {
|
if idx.btr != nil {
|
||||||
// Add new item to btree index.
|
// Add new item to btree index.
|
||||||
idx.btr.Set(item)
|
idx.btr.Set(item)
|
||||||
|
@ -512,6 +515,9 @@ func (db *DB) deleteFromDatabase(item *dbItem) *dbItem {
|
||||||
db.exps.Delete(pdbi)
|
db.exps.Delete(pdbi)
|
||||||
}
|
}
|
||||||
for _, idx := range db.idxs {
|
for _, idx := range db.idxs {
|
||||||
|
if !idx.match(pdbi.key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if idx.btr != nil {
|
if idx.btr != nil {
|
||||||
// Remove it from the btree index.
|
// Remove it from the btree index.
|
||||||
idx.btr.Delete(pdbi)
|
idx.btr.Delete(pdbi)
|
||||||
|
|
|
@ -1487,6 +1487,62 @@ func TestInsertsAndDeleted(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInsertDoesNotMisuseIndex(t *testing.T) {
|
||||||
|
db := testOpen(t)
|
||||||
|
defer testClose(db)
|
||||||
|
fail := func(a, b string) bool { t.Fatal("Misused index"); return false }
|
||||||
|
if err := db.CreateIndex("some", "a*", fail); err != nil {
|
||||||
|
// Only one item is eligible for the index, so no comparison is necessary.
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := db.Update(func(tx *Tx) error {
|
||||||
|
if _, _, err := tx.Set("a", "1", nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, _, err := tx.Set("b", "1", nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Update(func(tx *Tx) error {
|
||||||
|
_, _, err := tx.Set("b", "2", nil)
|
||||||
|
return err
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteDoesNotMisuseIndex(t *testing.T) {
|
||||||
|
db := testOpen(t)
|
||||||
|
defer testClose(db)
|
||||||
|
fail := func(a, b string) bool { t.Fatal("Misused index"); return false }
|
||||||
|
if err := db.CreateIndex("some", "a*", fail); err != nil {
|
||||||
|
// Only one item is eligible for the index, so no comparison is necessary.
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := db.Update(func(tx *Tx) error {
|
||||||
|
if _, _, err := tx.Set("a", "1", nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, _, err := tx.Set("b", "1", nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Update(func(tx *Tx) error {
|
||||||
|
_, err := tx.Delete("b")
|
||||||
|
return err
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test index compare functions
|
// test index compare functions
|
||||||
func TestIndexCompare(t *testing.T) {
|
func TestIndexCompare(t *testing.T) {
|
||||||
if !IndexFloat("1.5", "1.6") {
|
if !IndexFloat("1.5", "1.6") {
|
||||||
|
|
Loading…
Reference in New Issue