github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/merge/candidate.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2016 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 package merge 23 24 import ( 25 "context" 26 27 "github.com/dolthub/dolt/go/store/d" 28 "github.com/dolthub/dolt/go/store/types" 29 ) 30 31 // candidate represents a collection that is a candidate to be merged. This 32 // interface exists to wrap Maps, Sets and Structs with a common API so that 33 // threeWayOrderedSequenceMerge() can remain agnostic to which kind of 34 // collections it's actually working with. 35 type candidate interface { 36 diff(ctx context.Context, parent candidate, change chan<- types.ValueChanged) error 37 get(ctx context.Context, k types.Value) (types.Value, bool, error) 38 pathConcat(ctx context.Context, change types.ValueChanged, path types.Path) (out types.Path, err error) 39 getValue() types.Value 40 } 41 42 type mapCandidate struct { 43 m types.Map 44 } 45 46 func (mc mapCandidate) diff(ctx context.Context, p candidate, change chan<- types.ValueChanged) error { 47 return mc.m.Diff(ctx, p.(mapCandidate).m, change) 48 } 49 50 func (mc mapCandidate) get(ctx context.Context, k types.Value) (types.Value, bool, error) { 51 return mc.m.MaybeGet(ctx, k) 52 } 53 54 func (mc mapCandidate) pathConcat(ctx context.Context, change types.ValueChanged, path types.Path) (out types.Path, err error) { 55 out = append(out, path...) 56 if kind := change.Key.Kind(); kind == types.BoolKind || kind == types.StringKind || kind == types.FloatKind { 57 out = append(out, types.NewIndexPath(change.Key)) 58 } else { 59 h, err := change.Key.Hash(mc.m.Format()) 60 61 if err != nil { 62 return nil, err 63 } 64 65 out = append(out, types.NewHashIndexPath(h)) 66 } 67 return out, nil 68 } 69 70 func (mc mapCandidate) getValue() types.Value { 71 return mc.m 72 } 73 74 type setCandidate struct { 75 s types.Set 76 } 77 78 func (sc setCandidate) diff(ctx context.Context, p candidate, change chan<- types.ValueChanged) error { 79 return sc.s.Diff(ctx, p.(setCandidate).s, change) 80 } 81 82 func (sc setCandidate) get(ctx context.Context, k types.Value) (types.Value, bool, error) { 83 return k, true, nil 84 } 85 86 func (sc setCandidate) pathConcat(ctx context.Context, change types.ValueChanged, path types.Path) (out types.Path, err error) { 87 out = append(out, path...) 88 if kind := change.Key.Kind(); kind == types.BoolKind || kind == types.StringKind || kind == types.FloatKind { 89 out = append(out, types.NewIndexPath(change.Key)) 90 } else { 91 h, err := change.Key.Hash(sc.s.Format()) 92 93 if err != nil { 94 return nil, err 95 } 96 97 out = append(out, types.NewHashIndexPath(h)) 98 } 99 return out, nil 100 } 101 102 func (sc setCandidate) getValue() types.Value { 103 return sc.s 104 } 105 106 type structCandidate struct { 107 s types.Struct 108 } 109 110 func (sc structCandidate) diff(ctx context.Context, p candidate, change chan<- types.ValueChanged) error { 111 return sc.s.Diff(ctx, p.(structCandidate).s, change) 112 } 113 114 func (sc structCandidate) get(ctx context.Context, key types.Value) (types.Value, bool, error) { 115 if field, ok := key.(types.String); ok { 116 return sc.s.MaybeGet(string(field)) 117 } 118 119 return nil, false, nil 120 } 121 122 func (sc structCandidate) pathConcat(ctx context.Context, change types.ValueChanged, path types.Path) (out types.Path, err error) { 123 out = append(out, path...) 124 str, ok := change.Key.(types.String) 125 if !ok { 126 t, err := types.TypeOf(change.Key) 127 128 var typeStr string 129 if err == nil { 130 typeStr, _ = t.Describe(ctx) 131 } 132 133 d.Panic("Field names must be strings, not %s", typeStr) 134 } 135 return append(out, types.NewFieldPath(string(str))), nil 136 } 137 138 func (sc structCandidate) getValue() types.Value { 139 return sc.s 140 }