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

In order to support multiple index types, create interface types for prolly Maps, and make the tree.MutableMap class generic. #8555

Merged
merged 7 commits into from
Nov 14, 2024
2 changes: 1 addition & 1 deletion go/libraries/doltcore/doltdb/durable/artifact_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func RefFromArtifactIndex(ctx context.Context, vrw types.ValueReadWriter, idx Ar
panic("TODO")

case types.Format_DOLT:
b := shim.ValueFromArtifactMap(idx.(prollyArtifactIndex).index)
b := shim.ValueFromMap(idx.(prollyArtifactIndex).index)
return refFromNomsValue(ctx, vrw, b)

default:
Expand Down
25 changes: 22 additions & 3 deletions go/libraries/doltcore/doltdb/durable/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func RefFromIndex(ctx context.Context, vrw types.ValueReadWriter, idx Index) (ty
return refFromNomsValue(ctx, vrw, idx.(nomsIndex).index)

case types.Format_DOLT:
b := shim.ValueFromMap(idx.(prollyIndex).index)
b := shim.ValueFromMap(MapFromIndex(idx))
return refFromNomsValue(ctx, vrw, b)

default:
Expand All @@ -112,11 +112,11 @@ func indexFromAddr(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeS
return IndexFromNomsMap(v.(types.Map), vrw, ns), nil

case types.Format_DOLT:
pm, err := shim.MapFromValue(v, sch, ns, isKeylessTable)
m, err := shim.MapInterfaceFromValue(v, sch, ns, isKeylessTable)
if err != nil {
return nil, err
}
return IndexFromProllyMap(pm), nil
return IndexFromMapInterface(m), nil

default:
return nil, errNbfUnknown
Expand Down Expand Up @@ -238,11 +238,30 @@ func ProllyMapFromIndex(i Index) prolly.Map {
return i.(prollyIndex).index
}

// MapFromIndex unwraps the Index and returns the underlying map as an interface.
func MapFromIndex(i Index) prolly.MapInterfaceWithMutable {
switch indexType := i.(type) {
case prollyIndex:
return indexType.index
}
return i.(prollyIndex).index
}

// IndexFromProllyMap wraps a prolly.Map and returns it as an Index.
func IndexFromProllyMap(m prolly.Map) Index {
return prollyIndex{index: m}
}

// IndexFromMapInterface wraps a prolly.MapInterface and returns it as an Index.
func IndexFromMapInterface(m prolly.MapInterface) Index {
switch m := m.(type) {
case prolly.Map:
return IndexFromProllyMap(m)
default:
panic("unknown map type")
}
}

var _ Index = prollyIndex{}

// HashOf implements Index.
Expand Down
6 changes: 3 additions & 3 deletions go/libraries/doltcore/doltdb/durable/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,11 +850,11 @@ func (t doltDevTable) GetTableRows(ctx context.Context) (Index, error) {
if err != nil {
return nil, err
}
m, err := shim.MapFromValue(types.SerialMessage(rowbytes), sch, t.ns, false)
m, err := shim.MapInterfaceFromValue(types.SerialMessage(rowbytes), sch, t.ns, false)
if err != nil {
return nil, err
}
return IndexFromProllyMap(m), nil
return IndexFromMapInterface(m), nil
}

func (t doltDevTable) GetTableRowsWithDescriptors(ctx context.Context, kd, vd val.TupleDesc) (Index, error) {
Expand All @@ -863,7 +863,7 @@ func (t doltDevTable) GetTableRowsWithDescriptors(ctx context.Context, kd, vd va
if err != nil {
return nil, err
}
return IndexFromProllyMap(m), nil
return IndexFromMapInterface(m), nil
}

func (t doltDevTable) SetTableRows(ctx context.Context, rows Index) (Table, error) {
Expand Down
16 changes: 8 additions & 8 deletions go/libraries/doltcore/sqle/enginetest/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ var validationStages = []validator{
// validateChunkReferences checks for dangling chunks.
func validateChunkReferences(ctx context.Context, db sqle.Database) error {
validateIndex := func(ctx context.Context, idx durable.Index) error {
pm := durable.ProllyMapFromIndex(idx)
return pm.WalkNodes(ctx, func(ctx context.Context, nd tree.Node) error {
m := durable.MapFromIndex(idx)
return m.WalkNodes(ctx, func(ctx context.Context, nd tree.Node) error {
if nd.Size() <= 0 {
return fmt.Errorf("encountered nil tree.Node")
}
Expand Down Expand Up @@ -113,7 +113,7 @@ func validateSecondaryIndexes(ctx context.Context, db sqle.Database) error {
if err != nil {
return false, err
}
primary := durable.ProllyMapFromIndex(rows)
primary := durable.MapFromIndex(rows)

for _, def := range sch.Indexes().AllIndexes() {
set, err := t.GetIndexSet(ctx)
Expand All @@ -124,7 +124,7 @@ func validateSecondaryIndexes(ctx context.Context, db sqle.Database) error {
if err != nil {
return true, err
}
secondary := durable.ProllyMapFromIndex(idx)
secondary := durable.MapFromIndex(idx)

err = validateIndexConsistency(ctx, sch, def, primary, secondary)
if err != nil {
Expand All @@ -140,7 +140,7 @@ func validateIndexConsistency(
ctx context.Context,
sch schema.Schema,
def schema.Index,
primary, secondary prolly.Map,
primary, secondary prolly.MapInterface,
) error {
if schema.IsKeyless(sch) {
return validateKeylessIndex(ctx, sch, def, primary, secondary)
Expand All @@ -151,7 +151,7 @@ func validateIndexConsistency(

// printIndexContents prints the contents of |prollyMap| to stdout. Intended for use debugging
// index consistency issues.
func printIndexContents(ctx context.Context, prollyMap prolly.Map) {
func printIndexContents(ctx context.Context, prollyMap prolly.MapInterface) {
fmt.Printf("Secondary index contents:\n")
kd := prollyMap.KeyDesc()
iterAll, _ := prollyMap.IterAll(ctx)
Expand All @@ -164,7 +164,7 @@ func printIndexContents(ctx context.Context, prollyMap prolly.Map) {
}
}

func validateKeylessIndex(ctx context.Context, sch schema.Schema, def schema.Index, primary, secondary prolly.Map) error {
func validateKeylessIndex(ctx context.Context, sch schema.Schema, def schema.Index, primary, secondary prolly.MapInterface) error {
// Full-Text indexes do not make use of their internal map, so we may safely skip this check
if def.IsFullText() {
return nil
Expand Down Expand Up @@ -239,7 +239,7 @@ func validateKeylessIndex(ctx context.Context, sch schema.Schema, def schema.Ind
}
}

func validatePkIndex(ctx context.Context, sch schema.Schema, def schema.Index, primary, secondary prolly.Map) error {
func validatePkIndex(ctx context.Context, sch schema.Schema, def schema.Index, primary, secondary prolly.MapInterface) error {
// Full-Text indexes do not make use of their internal map, so we may safely skip this check
if def.IsFullText() {
return nil
Expand Down
2 changes: 1 addition & 1 deletion go/libraries/doltcore/sqle/index/dolt_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ var sharePool = pool.NewBuffPool()

func maybeGetKeyBuilder(idx durable.Index) *val.TupleBuilder {
if types.IsFormat_DOLT(idx.Format()) {
kd, _ := durable.ProllyMapFromIndex(idx).Descriptors()
kd, _ := durable.MapFromIndex(idx).Descriptors()
return val.NewTupleBuilder(kd)
}
return nil
Expand Down
10 changes: 5 additions & 5 deletions go/libraries/doltcore/sqle/writer/prolly_index_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func getPrimaryKeylessProllyWriter(ctx context.Context, t *doltdb.Table, schStat

type indexWriter interface {
Name() string
Map(ctx context.Context) (prolly.Map, error)
Map(ctx context.Context) (prolly.MapInterface, error)
ValidateKeyViolations(ctx context.Context, sqlRow sql.Row) error
Insert(ctx context.Context, sqlRow sql.Row) error
Delete(ctx context.Context, sqlRow sql.Row) error
Expand Down Expand Up @@ -101,7 +101,7 @@ func (m prollyIndexWriter) Name() string {
return ""
}

func (m prollyIndexWriter) Map(ctx context.Context) (prolly.Map, error) {
func (m prollyIndexWriter) Map(ctx context.Context) (prolly.MapInterface, error) {
return m.mut.Map(ctx)
}

Expand Down Expand Up @@ -247,7 +247,7 @@ func (m prollyIndexWriter) uniqueKeyError(ctx context.Context, keyStr string, ke

type prollySecondaryIndexWriter struct {
name string
mut *prolly.MutableMap
mut prolly.MutableMapInterface
unique bool
prefixLengths []uint16

Expand All @@ -273,8 +273,8 @@ func (m prollySecondaryIndexWriter) Name() string {
return m.name
}

func (m prollySecondaryIndexWriter) Map(ctx context.Context) (prolly.Map, error) {
return m.mut.Map(ctx)
func (m prollySecondaryIndexWriter) Map(ctx context.Context) (prolly.MapInterface, error) {
return m.mut.MapInterface(ctx)
}

func (m prollySecondaryIndexWriter) ValidateKeyViolations(ctx context.Context, sqlRow sql.Row) error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (k prollyKeylessWriter) Name() string {
return k.name
}

func (k prollyKeylessWriter) Map(ctx context.Context) (prolly.Map, error) {
func (k prollyKeylessWriter) Map(ctx context.Context) (prolly.MapInterface, error) {
return k.mut.Map(ctx)
}

Expand Down Expand Up @@ -202,7 +202,7 @@ func (writer prollyKeylessSecondaryWriter) Name() string {
}

// Map implements the interface indexWriter.
func (writer prollyKeylessSecondaryWriter) Map(ctx context.Context) (prolly.Map, error) {
func (writer prollyKeylessSecondaryWriter) Map(ctx context.Context) (prolly.MapInterface, error) {
return writer.mut.Map(ctx)
}

Expand Down
8 changes: 4 additions & 4 deletions go/libraries/doltcore/sqle/writer/prolly_table_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ func getSecondaryProllyIndexWriters(ctx context.Context, t *doltdb.Table, schSta
if err != nil {
return nil, err
}
idxMap := durable.ProllyMapFromIndex(idxRows)
idxMap := durable.MapFromIndex(idxRows)

keyDesc, _ := idxMap.Descriptors()

// mapping from secondary index key to primary key
writers[defName] = prollySecondaryIndexWriter{
name: defName,
mut: idxMap.Mutate(),
mut: idxMap.MutateInterface(),
unique: def.IsUnique,
prefixLengths: def.PrefixLengths,
idxCols: def.Count,
Expand Down Expand Up @@ -337,7 +337,7 @@ func (w *prollyTableWriter) table(ctx context.Context) (t *doltdb.Table, err err
return nil, err
}

t, err = w.tbl.UpdateRows(ctx, durable.IndexFromProllyMap(pm))
t, err = w.tbl.UpdateRows(ctx, durable.IndexFromMapInterface(pm))
if err != nil {
return nil, err
}
Expand All @@ -353,7 +353,7 @@ func (w *prollyTableWriter) table(ctx context.Context) (t *doltdb.Table, err err
if err != nil {
return nil, err
}
idx := durable.IndexFromProllyMap(sm)
idx := durable.IndexFromMapInterface(sm)

s, err = s.PutIndex(ctx, wrSecondary.Name(), idx)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go/store/prolly/address_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (c AddressMap) Editor() AddressMapEditor {
}

type AddressMapEditor struct {
addresses tree.MutableMap[stringSlice, address, lexicographic]
addresses tree.MutableMap[stringSlice, address, lexicographic, tree.StaticMap[stringSlice, address, lexicographic]]
}

func (wr AddressMapEditor) Add(ctx context.Context, name string, addr hash.Hash) error {
Expand Down
30 changes: 25 additions & 5 deletions go/store/prolly/artifact_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ type ArtifactMap struct {
valDesc val.TupleDesc
}

func (m ArtifactMap) Has(ctx context.Context, key val.Tuple) (ok bool, err error) {
return m.tuples.Has(ctx, key)
}

func (m ArtifactMap) ValDesc() val.TupleDesc {
return m.valDesc
}

func (m ArtifactMap) KeyDesc() val.TupleDesc {
return m.keyDesc
}

var _ MapInterface = (*ArtifactMap)(nil)

// NewArtifactMap creates an artifact map based on |srcKeyDesc| which is the key descriptor for
// the corresponding row map.
func NewArtifactMap(node tree.Node, ns tree.NodeStore, srcKeyDesc val.TupleDesc) ArtifactMap {
Expand Down Expand Up @@ -162,15 +176,21 @@ func (m ArtifactMap) Editor() *ArtifactsEditor {
keyDesc: m.keyDesc,
valDesc: m.valDesc,
maxPending: artifactMapPendingBufferSize,
flusher: ProllyFlusher{},
},
artKB: val.NewTupleBuilder(artKD),
artVB: val.NewTupleBuilder(artVD),
pool: m.Pool(),
}
}

// IterAll returns an iterator for all artifacts.
func (m ArtifactMap) IterAll(ctx context.Context) (ArtifactIter, error) {
// IterAll returns a MapIter for all artifacts.
func (m ArtifactMap) IterAll(ctx context.Context) (MapIter, error) {
return m.tuples.IterAll(ctx)
}

// IterAllArtifacts returns an iterator for all artifacts.
func (m ArtifactMap) IterAllArtifacts(ctx context.Context) (ArtifactIter, error) {
numPks := m.srcKeyDesc.Count()
tb := val.NewTupleBuilder(m.srcKeyDesc)
itr, err := m.tuples.IterAll(ctx)
Expand Down Expand Up @@ -279,15 +299,15 @@ func (m ArtifactMap) CountOfTypes(ctx context.Context, artTypes ...ArtifactType)
}

func (m ArtifactMap) iterAllOfType(ctx context.Context, artType ArtifactType) (artifactTypeIter, error) {
itr, err := m.IterAll(ctx)
itr, err := m.IterAllArtifacts(ctx)
if err != nil {
return artifactTypeIter{}, err
}
return artifactTypeIter{itr, artType}, nil
}

func (m ArtifactMap) iterAllOfTypes(ctx context.Context, artTypes ...ArtifactType) (multiArtifactTypeItr, error) {
itr, err := m.IterAll(ctx)
itr, err := m.IterAllArtifacts(ctx)
if err != nil {
return multiArtifactTypeItr{}, err
}
Expand Down Expand Up @@ -429,7 +449,7 @@ func (wr *ArtifactsEditor) Flush(ctx context.Context) (ArtifactMap, error) {
}

return ArtifactMap{
tuples: m.tuples,
tuples: m,
srcKeyDesc: wr.srcKeyDesc,
keyDesc: wr.mut.keyDesc,
valDesc: wr.mut.valDesc,
Expand Down
2 changes: 1 addition & 1 deletion go/store/prolly/commit_closure.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (c CommitClosure) AsHashSet(ctx context.Context) (hash.HashSet, error) {
}

type CommitClosureEditor struct {
closure tree.MutableMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering]
closure tree.MutableMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering, tree.StaticMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering]]
}

type CommitClosureKey []byte
Expand Down
58 changes: 58 additions & 0 deletions go/store/prolly/map_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package prolly

import (
"context"

"github.com/dolthub/dolt/go/store/hash"
"github.com/dolthub/dolt/go/store/pool"
"github.com/dolthub/dolt/go/store/prolly/tree"
"github.com/dolthub/dolt/go/store/val"
)

// MapInterface is a common interface for prolly-tree based maps.
type MapInterface interface {
Node() tree.Node
NodeStore() tree.NodeStore
Count() (int, error)
HashOf() hash.Hash
WalkNodes(ctx context.Context, cb tree.NodeCb) error
Descriptors() (val.TupleDesc, val.TupleDesc)
IterAll(ctx context.Context) (MapIter, error)
Pool() pool.BuffPool
Has(ctx context.Context, key val.Tuple) (ok bool, err error)
ValDesc() val.TupleDesc
KeyDesc() val.TupleDesc
}

// MapInterface is a common interface for prolly-tree based maps that can be used as the basis of a mutable map that
// implements MutableMapInterface.
type MapInterfaceWithMutable interface {
MapInterface
MutateInterface() MutableMapInterface
}

// MutableMapInterface is a common interface for prolly-tree based maps that can be mutated.
type MutableMapInterface interface {
NodeStore() tree.NodeStore
Put(ctx context.Context, key, value val.Tuple) error
Delete(ctx context.Context, key val.Tuple) error
Checkpoint(ctx context.Context) error
Revert(ctx context.Context)
HasEdits() bool
IterRange(ctx context.Context, rng Range) (MapIter, error)
MapInterface(ctx context.Context) (MapInterface, error)
}
Loading
Loading