github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/types/set.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 types 23 24 import ( 25 "context" 26 "fmt" 27 28 "github.com/dolthub/dolt/go/store/atomicerr" 29 "github.com/dolthub/dolt/go/store/d" 30 ) 31 32 var EmptySet Set 33 34 type Set struct { 35 orderedSequence 36 } 37 38 func newSet(seq orderedSequence) Set { 39 return Set{seq} 40 } 41 42 func NewSet(ctx context.Context, vrw ValueReadWriter, v ...Value) (Set, error) { 43 data := buildSetData(vrw.Format(), v) 44 ch, err := newEmptySetSequenceChunker(ctx, vrw) 45 46 if err != nil { 47 return EmptySet, err 48 } 49 50 for _, v := range data { 51 _, err := ch.Append(ctx, v) 52 53 if err != nil { 54 return EmptySet, err 55 } 56 } 57 58 seq, err := ch.Done(ctx) 59 60 if err != nil { 61 return EmptySet, err 62 } 63 64 return newSet(seq.(orderedSequence)), nil 65 } 66 67 // NewStreamingSet takes an input channel of values and returns a output 68 // channel that will produce a finished Set. Values that are sent to the input 69 // channel must be in Noms sortorder, adding values to the input channel 70 // out of order will result in a panic. Once the input channel is closed 71 // by the caller, a finished Set will be sent to the output channel. See 72 // graph_builder.go for building collections with values that are not in order. 73 func NewStreamingSet(ctx context.Context, vrw ValueReadWriter, ae *atomicerr.AtomicError, vChan <-chan Value) <-chan Set { 74 return newStreamingSet(vrw, vChan, func(vrw ValueReadWriter, vChan <-chan Value, outChan chan<- Set) { 75 go readSetInput(ctx, vrw, ae, vChan, outChan) 76 }) 77 } 78 79 type streamingSetReadFunc func(vrw ValueReadWriter, vChan <-chan Value, outChan chan<- Set) 80 81 func newStreamingSet(vrw ValueReadWriter, vChan <-chan Value, readFunc streamingSetReadFunc) <-chan Set { 82 d.PanicIfTrue(vrw == nil) 83 outChan := make(chan Set, 1) 84 readFunc(vrw, vChan, outChan) 85 return outChan 86 } 87 88 func readSetInput(ctx context.Context, vrw ValueReadWriter, ae *atomicerr.AtomicError, vChan <-chan Value, outChan chan<- Set) { 89 defer close(outChan) 90 91 ch, err := newEmptySetSequenceChunker(ctx, vrw) 92 if ae.SetIfError(err) { 93 return 94 } 95 96 var lastV Value 97 for v := range vChan { 98 if lastV != nil { 99 isLess, err := lastV.Less(vrw.Format(), v) 100 101 if ae.SetIfErrAndCheck(err) { 102 return 103 } 104 105 d.PanicIfFalse(isLess) 106 } 107 lastV = v 108 _, err := ch.Append(ctx, v) 109 110 if ae.SetIfError(err) { 111 return 112 } 113 } 114 seq, err := ch.Done(ctx) 115 116 if ae.SetIfError(err) { 117 return 118 } 119 120 outChan <- newSet(seq.(orderedSequence)) 121 } 122 123 // Diff computes the diff from |last| to |m| using the top-down algorithm, 124 // which completes as fast as possible while taking longer to return early 125 // results than left-to-right. 126 func (s Set) Diff(ctx context.Context, last Set, changes chan<- ValueChanged) error { 127 if s.Equals(last) { 128 return nil 129 } 130 return orderedSequenceDiffLeftRight(ctx, last.orderedSequence, s.orderedSequence, changes) 131 } 132 133 // DiffLeftRight computes the diff from |last| to |s| using a left-to-right 134 // streaming approach, optimised for returning results early, but not 135 // completing quickly. 136 func (s Set) DiffLeftRight(ctx context.Context, last Set, changes chan<- ValueChanged) error { 137 if s.Equals(last) { 138 return nil 139 } 140 return orderedSequenceDiffLeftRight(ctx, last.orderedSequence, s.orderedSequence, changes) 141 } 142 143 func (s Set) asSequence() sequence { 144 return s.orderedSequence 145 } 146 147 // Value interface 148 func (s Set) Value(ctx context.Context) (Value, error) { 149 return s, nil 150 } 151 152 func (s Set) WalkValues(ctx context.Context, cb ValueCallback) error { 153 err := iterAll(ctx, s, func(v Value, idx uint64) error { 154 return cb(v) 155 }) 156 157 return err 158 } 159 160 func (s Set) First(ctx context.Context) (Value, error) { 161 cur, err := newCursorAt(ctx, s.orderedSequence, emptyKey, false, false) 162 163 if err != nil { 164 return nil, err 165 } 166 167 if !cur.valid() { 168 return nil, nil 169 } 170 171 item, err := cur.current() 172 173 if err != nil { 174 return nil, err 175 } 176 177 return item.(Value), nil 178 } 179 180 func (s Set) At(ctx context.Context, idx uint64) (Value, error) { 181 if idx >= s.Len() { 182 panic(fmt.Errorf("out of bounds: %d >= %d", idx, s.Len())) 183 } 184 185 cur, err := newSequenceIteratorAtIndex(ctx, s.orderedSequence, idx) 186 187 if err != nil { 188 return nil, err 189 } 190 191 item, err := cur.current() 192 193 if err != nil { 194 return nil, err 195 } 196 197 return item.(Value), nil 198 } 199 200 func (s Set) Has(ctx context.Context, v Value) (bool, error) { 201 cur, err := newCursorAtValue(ctx, s.orderedSequence, v, false, false) 202 203 if err != nil { 204 return false, err 205 } 206 207 if !cur.valid() { 208 return false, nil 209 } 210 211 item, err := cur.current() 212 213 if err != nil { 214 return false, err 215 } 216 217 return item.(Value).Equals(v), nil 218 } 219 220 type setIterCallback func(v Value) (bool, error) 221 222 func (s Set) isPrimitive() bool { 223 return false 224 } 225 226 func (s Set) Iter(ctx context.Context, cb setIterCallback) error { 227 cur, err := newCursorAt(ctx, s.orderedSequence, emptyKey, false, false) 228 229 if err != nil { 230 return err 231 } 232 233 return cur.iter(ctx, func(v interface{}) (bool, error) { 234 return cb(v.(Value)) 235 }) 236 } 237 238 type setIterAllCallback func(v Value) error 239 240 func (s Set) IterAll(ctx context.Context, cb setIterAllCallback) error { 241 return iterAll(ctx, s, func(v Value, idx uint64) error { 242 return cb(v) 243 }) 244 } 245 246 func (s Set) Iterator(ctx context.Context) (SetIterator, error) { 247 return s.IteratorAt(ctx, 0) 248 } 249 250 func (s Set) IteratorAt(ctx context.Context, idx uint64) (SetIterator, error) { 251 cur, err := newSequenceIteratorAtIndex(ctx, s.orderedSequence, idx) 252 253 if err != nil { 254 return nil, err 255 } 256 257 return &setIterator{ 258 sequenceIter: cur, 259 s: s, 260 }, nil 261 } 262 263 func (s Set) IteratorFrom(ctx context.Context, val Value) (SetIterator, error) { 264 cur, err := newCursorAtValue(ctx, s.orderedSequence, val, false, false) 265 266 if err != nil { 267 return nil, err 268 } 269 270 return &setIterator{sequenceIter: cur, s: s}, nil 271 } 272 273 func (s Set) Format() *NomsBinFormat { 274 return s.format() 275 } 276 277 func (s Set) Edit() *SetEditor { 278 return NewSetEditor(s) 279 } 280 281 func buildSetData(nbf *NomsBinFormat, values ValueSlice) ValueSlice { 282 if len(values) == 0 { 283 return ValueSlice{} 284 } 285 286 SortWithErroringLess(ValueSort{values, nbf}) 287 288 uniqueSorted := make(ValueSlice, 0, len(values)) 289 last := values[0] 290 for i := 1; i < len(values); i++ { 291 v := values[i] 292 if !v.Equals(last) { 293 uniqueSorted = append(uniqueSorted, last) 294 } 295 last = v 296 } 297 298 return append(uniqueSorted, last) 299 } 300 301 func makeSetLeafChunkFn(vrw ValueReadWriter) makeChunkFn { 302 return func(level uint64, items []sequenceItem) (Collection, orderedKey, uint64, error) { 303 d.PanicIfFalse(level == 0) 304 setData := make([]Value, len(items)) 305 306 var lastValue Value 307 for i, item := range items { 308 v := item.(Value) 309 310 if lastValue != nil { 311 isLess, err := lastValue.Less(vrw.Format(), v) 312 313 if err != nil { 314 return nil, orderedKey{}, 0, err 315 } 316 317 d.PanicIfFalse(isLess) 318 } 319 lastValue = v 320 setData[i] = v 321 } 322 323 seq, err := newSetLeafSequence(vrw, setData...) 324 325 if err != nil { 326 return nil, orderedKey{}, 0, err 327 } 328 329 set := newSet(seq) 330 var key orderedKey 331 if len(setData) > 0 { 332 var err error 333 key, err = newOrderedKey(setData[len(setData)-1], vrw.Format()) 334 335 if err != nil { 336 return nil, orderedKey{}, 0, err 337 } 338 } 339 340 return set, key, uint64(len(items)), nil 341 } 342 } 343 344 func newEmptySetSequenceChunker(ctx context.Context, vrw ValueReadWriter) (*sequenceChunker, error) { 345 return newEmptySequenceChunker(ctx, vrw, makeSetLeafChunkFn(vrw), newOrderedMetaSequenceChunkFn(SetKind, vrw), hashValueBytes) 346 } 347 348 func (s Set) readFrom(nbf *NomsBinFormat, b *binaryNomsReader) (Value, error) { 349 panic("unreachable") 350 } 351 352 func (s Set) skip(nbf *NomsBinFormat, b *binaryNomsReader) { 353 panic("unreachable") 354 } 355 356 func (s Set) String() string { 357 panic("unreachable") 358 } 359 360 func (s Set) HumanReadableString() string { 361 panic("unreachable") 362 }