Skip to content

Commit

Permalink
persist all index configs and add tests (#288)
Browse files Browse the repository at this point in the history
Signed-off-by: Aaron Sutula <hi@asutula.com>
  • Loading branch information
asutula authored Mar 27, 2020
1 parent 205c7a6 commit 07555d0
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 21 deletions.
44 changes: 41 additions & 3 deletions db/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,54 @@ func (c *Collection) Indexes() map[string]Index {
// Adding an index will override any overlapping index values if they already exist.
// @note: This does NOT currently build the index. If items have been added prior to adding
// a new index, they will NOT be indexed a posteriori.
func (c *Collection) AddIndex(path string, unique bool) error {
c.indexes[path] = Index{
func (c *Collection) AddIndex(config IndexConfig) error {
indexKey := dsDBIndexes.ChildString(c.name)
exists, err := c.db.datastore.Has(indexKey)
if err != nil {
return err
}

indexes := map[string]IndexConfig{}

if exists {
indexesBytes, err := c.db.datastore.Get(indexKey)
if err != nil {
return err
}
if err = json.Unmarshal(indexesBytes, &indexes); err != nil {
return err
}
}

// if the index being added is for path ID
if config.Path == idFieldName {
// and there already is and index on ID
if _, exists := indexes[idFieldName]; exists {
// just return gracefully
return nil
}
}

indexes[config.Path] = config

indexBytes, err := json.Marshal(indexes)
if err != nil {
return err
}

if err := c.db.datastore.Put(indexKey, indexBytes); err != nil {
return err
}

c.indexes[config.Path] = Index{
IndexFunc: func(field string, value []byte) (ds.Key, error) {
result := gjson.GetBytes(value, field)
if !result.Exists() {
return ds.Key{}, ErrNotIndexable
}
return ds.NewKey(result.String()), nil
},
Unique: unique,
Unique: config.Unique,
}
return nil
}
Expand Down
27 changes: 27 additions & 0 deletions db/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ func TestNewCollection(t *testing.T) {
})
}

func TestAddIndex(t *testing.T) {
t.Parallel()
t.Run("CreateDBAndCollection", func(t *testing.T) {
t.Parallel()
db, clean := createTestDB(t)
defer clean()
collection, err := db.NewCollection(CollectionConfig{
Name: "Person",
Schema: util.SchemaFromInstance(&Person{}, false),
})
checkErr(t, err)

t.Run("AddNameUniqueIndex", func(t *testing.T) {
err := collection.AddIndex(IndexConfig{Path: "Name", Unique: true})
checkErr(t, err)
})
t.Run("AddAgeNonUniqueIndex", func(t *testing.T) {
err := collection.AddIndex(IndexConfig{Path: "Age", Unique: false})
checkErr(t, err)
})
t.Run("AddIDIndex", func(t *testing.T) {
err := collection.AddIndex(IndexConfig{Path: "ID", Unique: true})
checkErr(t, err)
})
})
}

func TestCreateInstance(t *testing.T) {
t.Parallel()
t.Run("Single", func(t *testing.T) {
Expand Down
30 changes: 12 additions & 18 deletions db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,21 @@ func (d *DB) reCreateCollections() error {
return err
}

var indexes []IndexConfig
var indexes map[string]IndexConfig
index, err := d.datastore.Get(dsDBIndexes.ChildString(name))
if err == nil && index != nil {
_ = json.Unmarshal(index, &indexes)
}

indexValues := make([]IndexConfig, len(indexes))
for _, value := range indexes {
indexValues = append(indexValues, value)
}

if _, err := d.NewCollection(CollectionConfig{
Name: name,
Schema: schema,
Indexes: indexes,
Indexes: indexValues,
}); err != nil {
return err
}
Expand Down Expand Up @@ -228,24 +233,13 @@ func (d *DB) NewCollection(config CollectionConfig) (*Collection, error) {
}
}

for _, cfg := range config.Indexes {
// @todo: Should check to make sure this is a valid field path for this schema
if err := c.AddIndex(cfg.Path, cfg.Unique); err != nil {
return nil, err
}
}

indexBytes, err := json.Marshal(config.Indexes)
if err != nil {
return nil, err
}
indexKey := dsDBIndexes.ChildString(config.Name)
exists, err = d.datastore.Has(indexKey)
if err != nil {
if err := c.AddIndex(IndexConfig{Path: idFieldName, Unique: true}); err != nil {
return nil, err
}
if !exists {
if err := d.datastore.Put(indexKey, indexBytes); err != nil {

for _, cfg := range config.Indexes {
// @todo: Should check to make sure this is a valid field path for this schema
if err := c.AddIndex(cfg); err != nil {
return nil, err
}
}
Expand Down

0 comments on commit 07555d0

Please sign in to comment.