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  }