diff --git a/cmd/genji/dbutil/dump.go b/cmd/genji/dbutil/dump.go index 693a42766..a0f6f2f76 100644 --- a/cmd/genji/dbutil/dump.go +++ b/cmd/genji/dbutil/dump.go @@ -129,7 +129,7 @@ func dumpTable(tx *genji.Tx, tableName string, w io.Writer) error { } _, err = fmt.Fprintf(w, "CREATE%s INDEX %s ON %s (%s);\n", u, index.Info.IndexName, index.Info.TableName, - index.Info.Paths) + index.Info.Paths[0]) if err != nil { return err } diff --git a/cmd/genji/shell/command.go b/cmd/genji/shell/command.go index df6805cff..a3a5c3965 100644 --- a/cmd/genji/shell/command.go +++ b/cmd/genji/shell/command.go @@ -120,7 +120,7 @@ func runIndexesCmd(db *genji.DB, tableName string, w io.Writer) error { return err } - fmt.Fprintf(w, "%s ON %s (%s)\n", index.IndexName, index.TableName, index.Paths) + fmt.Fprintf(w, "%s ON %s (%s)\n", index.IndexName, index.TableName, index.Paths[0]) return nil }) diff --git a/cmd/genji/shell/command_test.go b/cmd/genji/shell/command_test.go index 7689f5e6d..88ee869d1 100644 --- a/cmd/genji/shell/command_test.go +++ b/cmd/genji/shell/command_test.go @@ -162,6 +162,10 @@ func TestSaveCommand(t *testing.T) { require.Len(t, indexes, 1) require.Equal(t, "idx_a", indexes[0]) + index, err := tx.GetIndex("idx_a") + require.NoError(t, err) + require.Equal(t, []document.ValueType{document.DoubleValue}, index.Info.Types) + return nil }) require.NoError(t, err) @@ -177,7 +181,7 @@ func TestSaveCommand(t *testing.T) { // check that by iterating through the index and finding the previously inserted values var i int - err = idx.AscendGreaterOrEqual(document.Value{Type: document.DoubleValue}, func(v, k []byte) error { + err = idx.AscendGreaterOrEqual([]document.Value{document.Value{Type: document.DoubleValue}}, func(v, k []byte) error { i++ return nil }) diff --git a/database/catalog.go b/database/catalog.go index f1ecd8408..932b3f6cb 100644 --- a/database/catalog.go +++ b/database/catalog.go @@ -307,9 +307,10 @@ func (c *Catalog) ReIndex(tx *Transaction, indexName string) error { return c.buildIndex(tx, idx, tb) } +// TODO not yet compatible with composite index func (c *Catalog) buildIndex(tx *Transaction, idx *Index, table *Table) error { return table.Iterate(func(d document.Document) error { - // TODO + // TODO(JH) v, err := idx.Info.Paths[0].GetValueFromDocument(d) if err == document.ErrFieldNotFound { return nil @@ -318,7 +319,6 @@ func (c *Catalog) buildIndex(tx *Transaction, idx *Index, table *Table) error { return err } - // TODO err = idx.Set([]document.Value{v}, d.(document.Keyer).RawKey()) if err != nil { return stringutil.Errorf("error while building the index: %w", err) @@ -476,13 +476,13 @@ func (c *catalogCache) AddIndex(tx *Transaction, info *IndexInfo) error { return ErrTableNotFound } - // if the index is created on a field on which we know the type, - // create a typed index. + // if the index is created on a field on which we know the type then create a typed index. + // if the given info contained existing types, they are overriden. + info.Types = nil for _, fc := range ti.FieldConstraints { for _, path := range info.Paths { if fc.Path.IsEqual(path) { if fc.Type != 0 { - // TODO info.Types = append(info.Types, document.ValueType(fc.Type)) } diff --git a/database/config.go b/database/config.go index f8a2b5391..57e73c44e 100644 --- a/database/config.go +++ b/database/config.go @@ -619,7 +619,7 @@ type IndexInfo struct { // If set to true, values will be associated with at most one key. False by default. Unique bool - // If set, the index is typed and only accepts values of those types. + // If set, the index is typed and only accepts values of those types . Types []document.ValueType } @@ -631,14 +631,12 @@ func (i *IndexInfo) ToDocument() document.Document { buf.Add("index_name", document.NewTextValue(i.IndexName)) buf.Add("table_name", document.NewTextValue(i.TableName)) - // TODO check that vb := document.NewValueBuffer() for _, path := range i.Paths { vb.Append(document.NewArrayValue(pathToArray(path))) } buf.Add("paths", document.NewArrayValue(vb)) - // TODO check that if i.Types != nil { types := make([]document.Value, 0, len(i.Types)) for _, typ := range i.Types { @@ -674,6 +672,7 @@ func (i *IndexInfo) ScanDocument(d document.Document) error { return err } + i.Paths = nil err = v.V.(document.Array).Iterate(func(ii int, pval document.Value) error { p, err := arrayToPath(pval.V.(document.Array)) if err != nil { @@ -688,18 +687,13 @@ func (i *IndexInfo) ScanDocument(d document.Document) error { return err } - // i.Paths, err = arrayToPath(v.V.(document.Array)) - // if err != nil { - // return err - // } - v, err = d.GetByField("types") if err != nil && err != document.ErrFieldNotFound { return err } - // TODO refacto if err == nil { + i.Types = nil err = v.V.(document.Array).Iterate(func(ii int, tval document.Value) error { i.Types = append(i.Types, document.ValueType(tval.V.(int64))) return nil @@ -715,7 +709,17 @@ func (i *IndexInfo) ScanDocument(d document.Document) error { // Clone returns a copy of the index information. func (i IndexInfo) Clone() *IndexInfo { - return &i + c := i + + c.Paths = make([]document.Path, len(i.Paths)) + for i, p := range i.Paths { + c.Paths[i] = p.Clone() + } + + c.Types = make([]document.ValueType, len(i.Types)) + copy(c.Types, i.Types) + + return &c } type indexStore struct { diff --git a/document/document.go b/document/document.go index 491f8cde3..0931cd175 100644 --- a/document/document.go +++ b/document/document.go @@ -553,6 +553,12 @@ func (p Path) GetValueFromArray(a Array) (Value, error) { return p[1:].getValueFromValue(v) } +func (p Path) Clone() Path { + c := make(Path, len(p)) + copy(c, p) + return c +} + func (p Path) getValueFromValue(v Value) (Value, error) { switch v.Type { case DocumentValue: diff --git a/sql/parser/create.go b/sql/parser/create.go index 34fd7c06b..138b41fac 100644 --- a/sql/parser/create.go +++ b/sql/parser/create.go @@ -248,7 +248,8 @@ func (p *Parser) parseCreateIndexStatement(unique bool) (query.CreateIndexStmt, return stmt, newParseError(scanner.Tokstr(tok, lit), []string{"("}, pos) } - // TODO + // TODO(JH) clean when updating the optimizer. + // Uncommented, it breaks the index scan iterator. // if len(paths) != 1 { // return stmt, &ParseError{Message: "indexes on more than one path are not supported"} // }