func (n *node) init(tx *bolt.Tx, cfg *structConfig) error { bucket, err := n.CreateBucketIfNotExists(tx, cfg.Name) if err != nil { return err } // save node configuration in the bucket _, err = newMeta(bucket, n) if err != nil { return err } for fieldName, fieldCfg := range cfg.Fields { if fieldCfg.Index == "" { continue } switch fieldCfg.Index { case tagUniqueIdx: _, err = index.NewUniqueIndex(bucket, []byte(indexPrefix+fieldName)) case tagIdx: _, err = index.NewListIndex(bucket, []byte(indexPrefix+fieldName)) default: err = ErrIdxNotFound } if err != nil { return err } } return nil }
func getIndex(bucket *bolt.Bucket, idxKind string, fieldName string) (index.Index, error) { var idx index.Index var err error switch idxKind { case tagUniqueIdx: idx, err = index.NewUniqueIndex(bucket, []byte(indexPrefix+fieldName)) case tagIdx: idx, err = index.NewListIndex(bucket, []byte(indexPrefix+fieldName)) default: err = ErrIdxNotFound } return idx, err }
func TestUniqueIndex(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := storm.Open(filepath.Join(dir, "storm.db")) defer db.Close() err := db.Bolt.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucket([]byte("test")) assert.NoError(t, err) idx, err := index.NewUniqueIndex(b, []byte("uindex1")) assert.NoError(t, err) err = idx.Add([]byte("hello"), []byte("id1")) assert.NoError(t, err) err = idx.Add([]byte("hello"), []byte("id1")) assert.NoError(t, err) err = idx.Add([]byte("hello"), []byte("id2")) assert.Error(t, err) assert.Equal(t, index.ErrAlreadyExists, err) err = idx.Add(nil, []byte("id2")) assert.Error(t, err) assert.Equal(t, index.ErrNilParam, err) err = idx.Add([]byte("hi"), nil) assert.Error(t, err) assert.Equal(t, index.ErrNilParam, err) id := idx.Get([]byte("hello")) assert.Equal(t, []byte("id1"), id) id = idx.Get([]byte("goodbye")) assert.Nil(t, id) err = idx.Remove([]byte("hello")) assert.NoError(t, err) err = idx.Remove(nil) assert.NoError(t, err) id = idx.Get([]byte("hello")) assert.Nil(t, id) err = idx.Add([]byte("hello"), []byte("id1")) assert.NoError(t, err) err = idx.Add([]byte("hi"), []byte("id2")) assert.NoError(t, err) err = idx.Add([]byte("yo"), []byte("id3")) assert.NoError(t, err) list, err := idx.AllRecords(nil) assert.NoError(t, err) assert.Len(t, list, 3) opts := index.NewOptions() opts.Limit = 2 list, err = idx.AllRecords(opts) assert.NoError(t, err) assert.Len(t, list, 2) opts = index.NewOptions() opts.Skip = 2 list, err = idx.AllRecords(opts) assert.NoError(t, err) assert.Len(t, list, 1) assert.Equal(t, []byte("id3"), list[0]) opts = index.NewOptions() opts.Skip = 2 opts.Limit = 1 opts.Reverse = true list, err = idx.AllRecords(opts) assert.NoError(t, err) assert.Len(t, list, 1) assert.Equal(t, []byte("id1"), list[0]) err = idx.RemoveID([]byte("id2")) assert.NoError(t, err) id = idx.Get([]byte("hello")) assert.Equal(t, []byte("id1"), id) id = idx.Get([]byte("hi")) assert.Nil(t, id) id = idx.Get([]byte("yo")) assert.Equal(t, []byte("id3"), id) ids, err := idx.All([]byte("yo"), nil) assert.NoError(t, err) assert.Len(t, ids, 1) assert.Equal(t, []byte("id3"), ids[0]) err = idx.RemoveID([]byte("id2")) assert.NoError(t, err) err = idx.RemoveID([]byte("id4")) assert.NoError(t, err) return nil }) assert.NoError(t, err) }
func TestUniqueIndexRange(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := storm.Open(filepath.Join(dir, "storm.db")) defer db.Close() db.Bolt.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucket([]byte("test")) assert.NoError(t, err) idx, err := index.NewUniqueIndex(b, []byte("uindex1")) assert.NoError(t, err) for i := 0; i < 10; i++ { val, _ := gob.Codec.Marshal(i) err = idx.Add(val, val) assert.NoError(t, err) } min, _ := gob.Codec.Marshal(3) max, _ := gob.Codec.Marshal(5) list, err := idx.Range(min, max, nil) assert.Len(t, list, 3) assert.NoError(t, err) assertEncodedIntListEqual(t, []int{3, 4, 5}, list) min, _ = gob.Codec.Marshal(11) max, _ = gob.Codec.Marshal(20) list, err = idx.Range(min, max, nil) assert.Len(t, list, 0) assert.NoError(t, err) min, _ = gob.Codec.Marshal(7) max, _ = gob.Codec.Marshal(2) list, err = idx.Range(min, max, nil) assert.Len(t, list, 0) assert.NoError(t, err) min, _ = gob.Codec.Marshal(-5) max, _ = gob.Codec.Marshal(2) list, err = idx.Range(min, max, nil) assert.Len(t, list, 0) assert.NoError(t, err) min, _ = gob.Codec.Marshal(3) max, _ = gob.Codec.Marshal(7) opts := index.NewOptions() opts.Skip = 2 list, err = idx.Range(min, max, opts) assert.Len(t, list, 3) assert.NoError(t, err) assertEncodedIntListEqual(t, []int{5, 6, 7}, list) opts = index.NewOptions() opts.Limit = 2 list, err = idx.Range(min, max, opts) assert.Len(t, list, 2) assert.NoError(t, err) assertEncodedIntListEqual(t, []int{3, 4}, list) opts = index.NewOptions() opts.Reverse = true opts.Skip = 2 opts.Limit = 2 list, err = idx.Range(min, max, opts) assert.Len(t, list, 2) assert.NoError(t, err) assertEncodedIntListEqual(t, []int{5, 4}, list) return nil }) }