Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build index upon creation #371

Merged
merged 3 commits into from
Mar 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions database/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,22 @@ func (c *Catalog) CreateIndex(tx *Transaction, opts IndexInfo) error {
return err
}

return tx.getIndexStore().Insert(opts)
err = tx.getIndexStore().Insert(opts)
if err != nil {
return err
}

idx, err := c.GetIndex(tx, opts.IndexName)
if err != nil {
return err
}

tb, err := c.GetTable(tx, opts.TableName)
if err != nil {
return err
}

return c.buildIndex(tx, idx, tb)
}

// GetIndex returns an index by name.
Expand Down Expand Up @@ -289,7 +304,11 @@ func (c *Catalog) ReIndex(tx *Transaction, indexName string) error {
return err
}

return tb.Iterate(func(d document.Document) error {
return c.buildIndex(tx, idx, tb)
}

func (c *Catalog) buildIndex(tx *Transaction, idx *Index, table *Table) error {
return table.Iterate(func(d document.Document) error {
v, err := idx.Info.Path.GetValueFromDocument(d)
if err == document.ErrFieldNotFound {
return nil
Expand All @@ -298,7 +317,12 @@ func (c *Catalog) ReIndex(tx *Transaction, indexName string) error {
return err
}

return idx.Set(v, d.(document.Keyer).RawKey())
err = idx.Set(v, d.(document.Keyer).RawKey())
if err != nil {
return fmt.Errorf("error while building the index: %w", err)
}

return nil
})
}

Expand Down
48 changes: 35 additions & 13 deletions database/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,25 +287,55 @@ func TestCatalogCreate(t *testing.T) {
}

func TestTxCreateIndex(t *testing.T) {
t.Run("Should create an index and return it", func(t *testing.T) {
t.Run("Should create an index, build it and return it", func(t *testing.T) {
db, cleanup := newTestDB(t)
defer cleanup()
catalog := db.Catalog()

update(t, db, func(tx *database.Transaction) error {
return catalog.CreateTable(tx, "test", nil)
err := catalog.CreateTable(tx, "test", nil)
if err != nil {
return err
}

tb, err := tx.GetTable("test")
require.NoError(t, err)

for i := int64(0); i < 10; i++ {
_, err = tb.Insert(document.NewFieldBuffer().
Add("a", document.NewIntegerValue(i)).
Add("b", document.NewIntegerValue(i*10)),
)
require.NoError(t, err)
}

return nil
})

clone := catalog.Clone()

update(t, db, func(tx *database.Transaction) error {
err := catalog.CreateIndex(tx, database.IndexInfo{
IndexName: "idxFoo", TableName: "test", Path: parsePath(t, "foo"),
IndexName: "idx_a", TableName: "test", Path: parsePath(t, "a"),
})
require.NoError(t, err)
idx, err := tx.GetIndex("idxFoo")
idx, err := tx.GetIndex("idx_a")
require.NoError(t, err)
require.NotNil(t, idx)

var i int
err = idx.AscendGreaterOrEqual(document.Value{Type: document.DoubleValue}, func(v, k []byte) error {
var buf bytes.Buffer
err = document.NewValueEncoder(&buf).Encode(document.NewDoubleValue(float64(i)))
require.NoError(t, err)
enc := buf.Bytes()
require.Equal(t, enc, v)
i++
return nil
})
require.Equal(t, 10, i)
require.NoError(t, err)

return errDontCommit
})

Expand Down Expand Up @@ -491,7 +521,7 @@ func TestCatalogReIndex(t *testing.T) {
require.Equal(t, clone, catalog)
})

t.Run("Should reindex the right index", func(t *testing.T) {
t.Run("Should reindex the index", func(t *testing.T) {
db, cleanup := newTestDB(t)
defer cleanup()

Expand Down Expand Up @@ -523,14 +553,6 @@ func TestCatalogReIndex(t *testing.T) {
idx, err = tx.GetIndex("b")
require.NoError(t, err)

i = 0
err = idx.AscendGreaterOrEqual(document.Value{Type: document.IntegerValue}, func(val, key []byte) error {
i++
return nil
})
require.NoError(t, err)
require.Zero(t, i)

return errDontCommit
})

Expand Down
2 changes: 1 addition & 1 deletion database/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const (

var (
// ErrIndexDuplicateValue is returned when a value is already associated with a key
ErrIndexDuplicateValue = errors.New("duplicate")
ErrIndexDuplicateValue = errors.New("duplicate value")
)

// An Index associates encoded values with keys.
Expand Down
7 changes: 6 additions & 1 deletion database/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,12 @@ func (tx *Transaction) DropTable(name string) error {
// CreateIndex creates an index with the given name.
// If it already exists, returns ErrIndexAlreadyExists.
func (tx *Transaction) CreateIndex(opts IndexInfo) error {
return tx.db.catalog.CreateIndex(tx, opts)
err := tx.db.catalog.CreateIndex(tx, opts)
if err != nil {
return err
}

return tx.ReIndex(opts.IndexName)
}

// GetIndex returns an index by name.
Expand Down
30 changes: 23 additions & 7 deletions query/reindex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,35 @@ func TestReIndex(t *testing.T) {
CREATE TABLE test1;
CREATE TABLE test2;

INSERT INTO test1(a, b) VALUES (1, 'a'), (2, 'b');
INSERT INTO test2(a, b) VALUES (3, 'c'), (4, 'd');

CREATE INDEX idx_test1_a ON test1(a);
CREATE INDEX idx_test1_b ON test1(b);
CREATE INDEX idx_test2_a ON test2(a);
CREATE INDEX idx_test2_b ON test2(b);

INSERT INTO test1(a, b) VALUES (1, 'a'), (2, 'b');
INSERT INTO test2(a, b) VALUES (3, 'c'), (4, 'd');
`)
require.NoError(t, err)

// truncate all indexes
err = db.Update(func(tx *genji.Tx) error {
c := tx.DB().Catalog()
for _, idxName := range c.ListIndexes("") {
idx, err := c.GetIndex(tx.Transaction, idxName)
if err != nil {
return err
}

err = idx.Truncate()
if err != nil {
return err
}
}

return nil
})
require.NoError(t, err)

err = db.Exec(test.query)
if test.fails {
require.Error(t, err)
Expand All @@ -50,9 +69,7 @@ func TestReIndex(t *testing.T) {
require.NoError(t, err)

err = db.View(func(tx *genji.Tx) error {
idxList := tx.ListIndexes()

for _, idxName := range idxList {
for _, idxName := range tx.ListIndexes() {
idx, err := tx.GetIndex(idxName)
require.NoError(t, err)

Expand Down Expand Up @@ -82,5 +99,4 @@ func TestReIndex(t *testing.T) {
require.NoError(t, err)
})
}

}